You can use jq '.[] | .login, .id' to obtain each login followed by its id.
Do it in jq, but see @Kusalananda's answer first
jq -r '.host_components[].HostRoles.host_name | join(",")'
No, that's wrong. This is what you need:
jq -r '.host_components | map(.HostRoles.host_name) | join(",")'
Demo:
jq -r '.host_components | map(.HostRoles.host_name) | join(",")' <<DATA
{"host_components":[
{"HostRoles":{"host_name":"one"}},
{"HostRoles":{"host_name":"two"}},
{"HostRoles":{"host_name":"three"}}
]}
DATA
outputs
one,two,three
paste is the best tool to do this job:
your_command | paste -sd, -
Is it possible to output multiple values on a single line?
Option to return objects as a list of objects (separated by a comma)
Using jq to parse and display multiple fields in a json serially - Stack Overflow
Generate multi-select field from comma separated list field
You want to run a .context,.score filter on each element of v I think:
$ jq -r '.[] | [.c, .e, .score, (.v[] | .context,.score)] | @csv' file.json
"A","B",0.99,"asdf",0.98,"bcdfd",0.97
This is equivalent to using the builtin map function without assembling the results back into an array.
The following creates a JSON-encoded CSV record for each top-level array element, and then extracts and decodes them. For each of the top-level elements, the values of the sub-array is incorporated by "flattening" the array.
jq -r 'map([ .c,.e,.score, (.v|map([.context, .score])) ] | flatten | @csv)[]' file
Given a test document equivalent of the following:
[
{
"c": "A",
"e": "B",
"score": 0.99,
"v": [
{ "context": "asdf", "score": 0.98, "url": "..." },
{ "context": "bcdfd", "score": 0.97, "url": "..." }
]
},
{
"c": "A",
"e": "B",
"score": 0.99,
"v": [
{ "context": "asdf", "score": 0.98, "url": "..." },
{ "context": "asdf", "score": 0.98, "url": "..." },
{ "context": "bcdfd", "score": 0.97, "url": "..." }
]
},
{
"c": "A",
"e": "B",
"score": 0.99,
"v": [
{ "context": "asdf", "score": 0.98, "url": "..." },
{ "context": "asdf", "score": 0.98, "url": "..." },
{ "context": "asdf", "score": 0.98, "url": "..." },
{ "context": "bcdfd", "score": 0.97, "url": "..." }
]
}
]
... we get
"A","B",0.99,"asdf",0.98,"bcdfd",0.97
"A","B",0.99,"asdf",0.98,"asdf",0.98,"bcdfd",0.97
"A","B",0.99,"asdf",0.98,"asdf",0.98,"asdf",0.98,"bcdfd",0.97
One could also reorder the operations so that a single use of the @csv operator gets a set of arrays (rather than repeatedly using @csv on single arrays):
jq -r 'map([ .c,.e,.score, (.v|map([.context, .score])) ] | flatten)[]|@csv' file
I recommend using String Interpolation:
jq '.users[] | "\(.first) \(.last)"'
We are piping down the result of .users[] to generate the string ".first .last" using string interpolation. \(foo) syntax is used for string interpolation in jq. So, for the above example, it becomes "Stevie Wonder" (".users[].first .users[].second" working elementwise) and "Michael Jackson".
jq reference: String interpolation
You can use addition to concatenate strings.
Strings are added by being joined into a larger string.
jq '.users[] | .first + " " + .last'
The above works when both first and last are string. If you are extracting different datatypes(number and string), then we need to convert to equivalent types. Referring to solution on this question. For example.
jq '.users[] | .first + " " + (.number|tostring)'