1

I'm trying to parse a JSON file with jq but I can't get it right. How do I parse the following JSON to:

  • A single nested object and also add additional top level keys ("cities", "uppsala", and "locations" in the example)
  • Use the values for the keys name as keys for the objects?

(shortened version of source json):

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "name": "Uppsala domkyrka"
      },
      "geometry": {
        "coordinates": [
          17.6336159,
          59.8581466
        ]
      }
    },
    {
      "type": "Feature",
      "properties": {
        "name": "Uppsala moské"
      },
      "geometry": {
        "coordinates": [
          17.6382165,
          59.874003
        ]
      }
    }
  ]
}

I'm trying to parse it to this format:

{
  "cities": {
    "uppsala": {
      "locations": {
        "Uppsala domkyrka": {
          "name": "Uppsala domkyrka",
          "coordinates": {
            "_latitude": 59.854,
            "_longitude": 17.6261
          }
        },
        "Uppsala moské": {
          "name": "Uppsala moské",
          "coordinates": {
            "_latitude": 59.8581,
            "_longitude": 17.6336
          }
        }
      }
    }
  }
}

This is the command I've arrived at so far:

[.features[] | {name: .properties.name, coordinates: {_latitude: .geometry.coordinates[0], _longitude: .geometry.coordinates[1]}}]

To produce this, which is not quite right:

[
  {
    "name": "Uppsala domkyrka",
    "coordinates": {
      "_latitude": 17.6336159,
      "_longitude": 59.8581466
    }
  },
  {
    "name": "Uppsala moské",
    "coordinates": {
      "_latitude": 17.6382165,
      "_longitude": 59.874003
    }
  }
]

I haven't managed to get the values for name as keys for the objects.

Any ideas? I've been reading SO for hours and pulling my hair out..

2
  • Your expected output isn't a valid JSON, you can't have duplicate keys of same name ID Commented Jul 24, 2019 at 16:12
  • Thanks for pointing that out promptly @Inian and @ peak - clearly a misunderstanding on my part. I believe it's corrected, does it make sense now? Commented Jul 24, 2019 at 17:50

1 Answer 1

1

Since you want to hard-code the three top-most keys, the key to a solution is add:

{
  "cities": {
    "uppsala": {
      "locations":
        [.features[]
         | {name: .properties.name,
            coordinates:
              {_latitude: .geometry.coordinates[0],
               _longitude: .geometry.coordinates[1]
              }
            }
         | {(.name): .}
        ] | add
    }
  }
}

If you don't want the redundancy of the name, you could replace {(.name): .} with:

{(.name): del(.name)}

A more compact variant

The critical add gets a bit lost in the above, so you might like to consider this equivalent alternative:

[.features[]
 | {name: .properties.name,
    coordinates:
      { _latitude: .geometry.coordinates[0],
        _longitude: .geometry.coordinates[1]
      }
   } | {(.name): .} ]
| add as $v
| ({} | .cities.uppsala.locations = $v)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.