Get the index of the array element in JSON with jq

3.1k Views Asked by At

I have the following type of json:

{
  "foo": "hello",
  "bar": [
    {
      "key": "k1",
      "val": "v1"
    },
    {
      "key": "k2",
      "val": "v2"
    },
    {
      "key": "k3",
      "val": "v3"
    }
  ]
}

I want to output the following:

"hello", 1, "k1", "v1"
"hello", 2, "k2", "v2"
"hello", 3, "k3", "v3"

I am using jq to tranform this and the answer should also be with a jq transformation.

I am currently at:

echo '{"foo": "hello","bar": [{"key": "k1","val": "v1"},{"key": "k2","val": "v2"},{"key": "k3","val": "v3"} ]}' | jq -c -r '.bar[] as $b | [.foo, ($b | .key, .val)] | @csv'

Which gives me:

"hello","k1","v1"
"hello","k2","v2"
"hello","k3","v3"

How can I also get the index to show of the array element being parsed?

2

There are 2 best solutions below

0
On BEST ANSWER

You could convert the array to entries to access the index and the value. Then you can build out the CSV rows.

$ jq -r '[.foo] + (.bar | to_entries[] | [.key+1,.value.key,.value.val]) | @csv' input.json
"hello",1,"k1","v1"
"hello",2,"k2","v2"
"hello",3,"k3","v3"
0
On

Assuming you have access to jq 1.5 and that the key/val keys are presented in that order:

jq -r '.foo as $foo 
  | foreach .bar[] as $i (0; .+1; [$foo, .] + [$i[]])
  | @csv'

would produce:

"hello",1,"k1","v1"
"hello",2,"k2","v2"
"hello",3,"k3","v3"

The -r option is often used with @csv to convert the JSON string that would otherwise be produced by @csv into a comma-separated list of values.

If you really want to join with ", ", then it's a bit messier, but if you're not worried about the functionality that @csv provides, here's one way:

$ jq -r '"\"\(.foo)\"" as $foo
    | foreach .bar[] as $i
        (0; .+1; "\($foo), \(.), \($i | map("\"\(.)\"")|join(", "))")' 

This produces:

"hello", 1, "k1", "v1"
"hello", 2, "k2", "v2"
"hello", 3, "k3", "v3"

If your jq does not have foreach then you could similarly use reduce, but it might be easier to upgrade.