如何拆分 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
),但我保持简单,以便您可以轻松地进行修改以满足您更详细的要求。
我正在尝试使用 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
),但我保持简单,以便您可以轻松地进行修改以满足您更详细的要求。