将具有不可预测键值对的对象数组的 JSON 转换为 CSV

Convert JSON with array of objects of unpredictable key-value-pairs to CSV

我知道了 JSON:

[
  {
    "id": "1",
    "tag": [
      {
        "k": "name",
        "v": "Luxor"
      }
    ]
  },
  {
    "id": "2",
    "tag": [
      {
        "k": "name",
        "v": "Farflame"
      },
      {
        "k": "magic",
        "v": "30"
      }
    ]
  }
]

我想创建一个包含“id”、“name”和“magic”的 CSV。如果元素不存在,则应设置一个空字符串:

"id","name","magic"
"1","Luxor",""
"2","Farflame","30"

我快到了,但是如果不存在“magic”我就无法得到空字符串:

me@MBA test % jq -r '.[] | [.id, (.tag[] | select(.k=="name") | .v), (.tag[] | select(.k=="magic") | .v)] | @csv' simple.json
"1","Luxor"
"2","Farflame","30"

如您所见,id 为“1”的行只有两个单元格,因为“tag”中没有“magic”元素。我尝试了各种 if 语句,但没能找到一个符合我要求的语句。

动机

上面的玩具示例类似于 OpenStreetMap 导出的 OSM XML 代码。要将一些 OpenStreetMap 数据导入数据库,转换为表格结构是至关重要的一步。 OSM 将节点(或方式或关系)的所有标签存储在具有键“@k”和“@v”的对象数组中;您无法预测哪些键存在以及以什么顺序存在。

select 扩展性不佳。相反,我会编写一个类似于 from_entries 的函数,用于将 tag 数组转换为对象,并像这样使用它:

def f: map({(.k): .v}) | add;
.[] | [.id] + (.tag | f | [.name, .magic]) | @csv

Online demo