11

I'm trying to use jq to parse a NOAA data feed into just the values I need:

http://forecast.weather.gov/MapClick.php?FcstType=json&lat=39.56&lon=-104.85

I'm able to (separately) extract the two arrays I'm looking to combine:

$ cat noaa.json | jq .time.startPeriodName
[
  "Today",
  "Tonight",
  "Friday",
  "Friday Night",
  "Saturday",
  "Saturday Night",
  "Sunday",
  "Sunday Night",
  "Monday",
  "Monday Night",
  "Tuesday",
  "Tuesday Night",
  "Wednesday"
]

$ cat noaa.json | jq .data.weather
[
  "Mostly Sunny",
  "Mostly Cloudy",
  "Mostly Sunny",
  "Partly Cloudy",
  "Slight Chance Showers",
  "Slight Chance Snow Showers",
  "Slight Chance Snow Showers then Mostly Sunny",
  "Mostly Clear",
  "Mostly Sunny",
  "Partly Cloudy",
  "Mostly Sunny",
  "Partly Cloudy",
  "Mostly Sunny"
]

I'd like to combine the two arrays together into a single object like this:

{ 
   "Today": "Mostly Sunny",
   "Tonight": "Mostly Cloudy",
   ...
   "Wednesday": "Mostly Sunny"
}

I'd be grateful if someone could point me in the right direction. I feel like the answer is probably in the map operator, but I haven't been able to figure it out.

peak
  • 105,803
  • 17
  • 152
  • 177
Scott
  • 1,164
  • 2
  • 14
  • 24

1 Answers1

20

Yes, map is a good way to go. The key here is to use it with transpose/0, which can be used as though it were a "zip" function:

 [.time.startPeriodName, .data.weather]
 | transpose
 | map( {(.[0]): .[1]})

The output begins as follows:

[
  {
    "Today": "Mostly Sunny"
  },
  {
    "Tonight": "Mostly Cloudy"
  },
  ...

So, to produce a single JSON object, simply add the add filter to the pipeline.

peak
  • 105,803
  • 17
  • 152
  • 177
  • 1
    This is helpful. Is there a way I can run `transpose` and `map` so that I end up with a single object instead of an array of objects? or perhaps another transformation that can merge this resulting array into a single object? – Scott Dec 08 '16 at 18:56
  • 2
    Ah, I added `| add` to the end and got what I wanted. – Scott Dec 08 '16 at 18:57
  • Here's an example that references a path to get to the initial array. `jq ".results[0].result.tag | [.classes, .probs] | transpose | map( {(.[0]): .[1]} ) | add"` myinput.txt – BSalita Jan 23 '17 at 14:30
  • The array from which I got my object keys was of the `number` type, I simply used `.[0]|tostring` inside the map (e.g. pipe to `tostring`) following [the answer to this question](https://stackoverflow.com/questions/35365769/how-do-i-use-jq-to-convert-number-to-string) – crackpotHouseplant Jan 03 '20 at 05:50
  • 1
    Another option to build a dict from a list of pairs is `map({key: .[0], value: .[1]}) | to_entries` – augurar Mar 12 '21 at 18:51