Search code examples
jsonopenstreetmapgeojsonjq

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:

[
  {
    "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": [
    {
      "\"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

Is there a more elegant/shorter jq instruction i can use, also giving me the desired output as stated above?


Solution

  • found a satisfying solution while fiddling around on 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

    edit2: comma tolerant and includes nodes w/o 'other_tags'