Join a list of json values using jq

Viewed 56

I'm attempting to reduce this list of names to a single line of text.

I have JSON like this:

{
    "speakers": [
        {
            "firstName": "Abe",
            "lastName": "Abraham"
        },
        {
            "firstName": "Max",
            "lastName": "Miller"
        }
    ]
}

Expected output:

Abe Abraham and Max Miller

One of the many attempts I've made is this:

jq -r '.speakers[] | ["\(.firstName) \(.lastName)"] | join(" and ")'

The results are printed out on separate lines like this:

Abe Abraham
Max Miller

I think the join command is just joining the single-element array piped to it (one name per array). How can I get the full list of names passed to join as a single array, so I get the expected output shown above?

2 Answers

You're getting an array for each speaker that way. What you want is a single array containing all so that you can join them, which is done like this:

.speakers | map("\(.firstName) \(.lastName)") | join(" and ")
$ jq -c '.speakers[] | [ "\(.firstName) \(.lastName)" ]' speakers.json
["Abe Abraham"]
["Max Miller"]

If you move your opening [ you get a single array with all the names.

$ jq -c '[ .speakers[] | "\(.firstName) \(.lastName)" ]' speakers.json
["Abe Abraham","Max Miller"]

Which you can pass to join()

$ jq -r '[ .speakers[] | "\(.firstName) \(.lastName)" ] | join(" and ")' speakers.json
Abe Abraham and Max Miller

If there are no other keys you can also write it like:

$ jq -r '[.speakers[] | join(" ")] | join(" and ")' speakers.json 
Abe Abraham and Max Miller
Related