1

I am trying to create a one size fits all jq command to dump out all keys containing data, eg number,string,null,boolean

When it hits a value that is an array, I don't want the array name printed, rather it should look inside the array and extract the key names from inside the array.

The example output would be like such...

coord.lon
coord.lat
weather.0
weather.0.id
weather.0.main
weather.0.description
weather.0.icon
base

I have the following bit that works, but it returns the parent keys which are arrays and I don't need those, just the subkeys.

jq -r 'paths | map(.|tostring)|join(".")' weather.json

Can anyone provide any help? I'm struggling pretty badly.

Example json

  {
  "coord": {
    "lon": -90.85,
    "lat": 38.8
  },
  "weather": [
    {
      "id": 501,
      "main": "Rain",
      "description": "moderate rain",
      "icon": "10d"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 38.19,
    "pressure": 1020,
    "humidity": 100,
    "temp_min": 36,
    "temp_max": 39.99
  },
  "visibility": 4023,
  "wind": {
    "speed": 4.7,
    "deg": 330
  },
  "rain": {
    "1h": 1.82
  },
  "clouds": {
    "all": 75
  },
  "dt": 1572448290,
  "sys": {
    "type": 1,
    "id": 4178,
    "country": "US",
    "sunrise": 1572438477,
    "sunset": 1572476760
  },
  "timezone": -18000,
  "id": 0,
  "name": "Wentzville",
  "cod": 200
}
2
  • 1
    why should "coord" itself be skipped? it's not an array Oct 30 '19 at 19:22
  • You are correct, should have been more specific... I am looking for any fields that contain data... I believe coord is an object, so I would want the fields that are beneath coord.
    – Ken
    Oct 30 '19 at 19:59
1

You could delete arrays first, e.g.:

del(.[] | select(type=="array"))

To only keep objects do something like this:

<infile.json jq -r '
del(.[] | select(type!="object")) |
paths                             |
map(tostring)                     |
select(length==2)                 |
join(".")
'

Output:

coord.lon
coord.lat
main.temp
main.pressure
main.humidity
main.temp_min
main.temp_max
wind.speed
wind.deg
rain.1h
clouds.all
sys.type
sys.id
sys.country
sys.sunrise
sys.sunset

Edit

Perhaps you want a combination of the two answers?

paths(scalars)      |
select(length >= 2) |
map(tostring)       |
join(".")

Output:

coord.lon
coord.lat
weather.0.id
weather.0.main
weather.0.description
weather.0.icon
main.temp
main.pressure
main.humidity
main.temp_min
main.temp_max
wind.speed
wind.deg
rain.1h
clouds.all
sys.type
sys.id
sys.country
sys.sunrise
sys.sunset
2
  • Thanks @Thor That is almost spot on! However, it is chopping weather.0.id weather.0.main weather.0.description weather.0.icon which all have data.
    – Ken
    Oct 30 '19 at 21:05
  • Thank you so much! This is absolutely perfect! You taught me something new today! Appreciate it more than you know!!
    – Ken
    Oct 31 '19 at 13:15
0

this is working :

jq -r 'paths(scalars) | map(.|tostring)|join(".")' weather.json

result

coord.lon
coord.lat
weather.0.id
weather.0.main
weather.0.description
weather.0.icon
base
main.temp
main.pressure
main.humidity
main.temp_min
main.temp_max
visibility
wind.speed
wind.deg
rain.1h
clouds.all
dt
sys.type
sys.id
sys.country
sys.sunrise
sys.sunset
timezone
id
name
cod

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.