Search code examples
jsonexport-to-csvjq

How to print object element for each internal array element in jq


I have JSON that looks like this:

test.json

[
  {
    "item1": {
      "item2": 123,
      "array1": [
        {
          "item3": 456,
          "item4": "teststring"
        },
        {
          "item3": 789,
          "item4": "teststring2"
        }
      ]
    }
  }
]

I am trying to print it out in the following format:

123, 456, teststring
123, 789, teststring2

I tried to do it like this:

cat test.json | jq -r '.[].item1.item2, (.[].item1.array1[] | .item3, .item4)' | xargs printf "%s, %s, %s\n"

But the result is that item2 is printed, followed by item3 and item4 in the first line, and then only item3 and item4 are printed in the next line, like so:

123, 456, teststring
789, teststring2, 

How can I make the element on the outside of the array print for every set of elements that are printed from within the array?


Solution

  • Doing the processing of the output with shell's printf() with xargs is not needed as you can do the processing entirely in jq itself.

    You need to iterate over the values of .item3 and .item4 each time for one unique value of .item2. To have the result in proper CSV format, format the array using @csv and for tabular representation you can use @tsv

    jq -r '.[].item1 as $data | $data.array1[] | [ $data.item2 , .item3 , .item4 ] | @csv' json
    

    Also it does not make sense to lose quotes around the .item4 values in your expected output, as they are the expected to be retained in a valid JSON string attribute.

    If you still need to loose the quotes and represent them as raw strings, you can use join on the formed array

    jq -r '.[].item1 as $data | $data.array1[] | [ ($data.item2|tostring) , (.item3|tostring) , .item4 ]|join(", ")'