如何拆分 json 中的字符串值并使用 jq 转换为嵌套对象?

How to split a string value in json and convert to nested objects using jq?

我正在尝试使用 jq 来转换这样的东西:

[
  {
    "type": "Feature",
    "properties": {
      "osm_id": "172544",
      "highway": "crossing",
      "other_tags": "\"crossing\"=>\"uncontrolled\",\"tactile_paving\"=>\"yes\""
    },
    "geometry": {
      "type": "Point",
      "coordinates": [
        13.3432342,
        52.5666157
      ]
    }
  }
]

进入这个:

[
  {
    "type": "Feature",
    "properties": {
      "osm_id": "172544",
      "highway": "crossing",
      "other_tags": {
        "crossing": "uncontrolled",
        "tactile_paving": "yes"
      }
    },
    "geometry": {
      "type": "Point",
      "coordinates": [
        13.3432342,
        52.5666157
      ]
    }
  }
]

现在,这是我的进度:

jq 'map(try(.properties.other_tags |= split(",") // .)) | map(try(.properties.other_tags[] |= split("=>") // .)) | map(try(.properties.other_tags[] |= { (.[0]) : .[1] } // .))' example.json

但是 "other_tags" 的输出看起来像这样:

  "other_tags": [
    {
      "\"crossing\"": "\"uncontrolled\""
    },
    {
      "\"tactile_paving\"": "\"yes\""
    }
  ]

我很确定这没有达到应有的性能。

用于转换osm导出,比较大

是否有更多 elegant/shorter 我可以使用的 jq 指令,也能给我如上所述的所需输出?

jqplay 上摆弄时找到了令人满意的解决方案:

jq '.features
  | map(try(.properties.other_tags |=
            (split("\",\"")
             | join("\"##strsplit##\"")
             | split("##strsplit##")
             | .[] |= split("=>") 
             | .[] |= {(.[0][1:-1]): (.[1][1:-1])}
             | add)) // .)'

编辑:更改了数组索引,感谢 peak 的评论

edit2:逗号容错并包含节点 w/o 'other_tags'

你也可以使用这个:

<file jq '[.[] | try(.properties.other_tags |= ("{" + gsub("=>"; ":") + "}" | fromjson))//.]'

这会将大括号 {} 添加到所需的字符串中,并将 => 替换为 :。然后使用命令 fromjson 将字符串转换为 JSON 对象。

如果未找到 .properties.other_tags,该命令不会更改 JSON 数据。

这是一个解决方案,假设输入可以被解析为逗号分隔的段,匹配以下正则表达式(表示为 JSON):

"\"(?<key>[^\"]+)\"=>\"(?<value>[^\"]+)\""

# emit a stream
def unwrap:
  . as $s
  | if length==0 then empty
    else match( "\"(?<key>[^\"]+)\"=>\"(?<value>[^\"]+)\",?" )
    | (.captures|map({(.name): .string})|add), 
      ( $s[.length:]|unwrap)
    end
;

 map( .properties.other_tags |= ([unwrap]|from_entries) )

这种方法具有允许在键和值中使用逗号和出现“=>”的(潜在)优势。当然,可以加强实施(例如,像您所做的那样使用 try),但我保持简单,以便您可以轻松地进行修改以满足您更详细的要求。