简体   繁体   English

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

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

I am trying to use jq to convert something like this:我正在尝试使用 jq 来转换这样的东西:

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

into this:进入这个:

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

right now, this is my progress:现在,这是我的进步:

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

but the output of "other_tags" looks like this:但“other_tags”的输出如下所示:

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

I am pretty sure this is not as performant as it could be.我很确定这并没有达到应有的性能。

It's used to transform osm exports, which are fairly big用来转换osm的exports,比较大

Is there a more elegant/shorter jq instruction i can use, also giving me the desired output as stated above?是否有我可以使用的更优雅/更短的 jq 指令,还可以提供上述所需的输出?

You could also use this:你也可以使用这个:

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

This adds curly braces { and } to the wanted string and replace => by : .这将花括号{}到想要的字符串中,并将=>替换=> : The string is then converted as a JSON object with the command fromjson .然后使用fromjson命令将该字符串转换为 JSON 对象。

The command doesn't change the JSON data if the .properties.other_tags isn't found.如果未找到.properties.other_tags该命令不会更改 JSON 数据。

found a satisfying solution while fiddling around on jqplay :在摆弄jqplay时找到了一个令人满意的解决方案:

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

edit: changed the array index, thanks to peak for your comment编辑:更改了数组索引,感谢 peak 的评论

edit2: comma tolerant and includes nodes w/o 'other_tags'编辑 2:容忍逗号并包括没有“other_tags”的节点

Here's a solution that assumes the input can be parsed into comma-separated segments matching the following regex (expressed as 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) )

This approach has the (potential) advantage of allowing commas and occurrences of "=>" within the keys and values.这种方法的(潜在)优势是允许在键和值中使用逗号和出现“=>”。 Of course the implementation can be robustified (eg using try as you have done), but I've kept it simple so you can easily make modifications to meet your more detailed requirements.当然,实现可以被加强(例如,像您一样使用try ),但我一直保持简单,因此您可以轻松地进行修改以满足您更详细的要求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM