0

Given a JSON file like this,

[
  {
    "h1": "x1",
    "h2": "x2"
  },
  {
    "h1": "y1",
    "h2": "y2"
  }
]

I extract it as a headed TSV using the following jq code. But I need to specify the header names twice. Is there a way to just specify the header names once? Thanks.

[
    "h1"
    , "h2"
], (.[] | [ 
    .h1
    , .h2
]) | @tsv
peak
  • 105,803
  • 17
  • 152
  • 177
user1424739
  • 11,937
  • 17
  • 63
  • 152
  • 1
    If all your objects always have those two keys and no other, you don't need to specify the headers even once : `[.[0] | keys[]], .[] | map(values) | @tsv` will [work just fine](https://jqplay.org/s/jzio98rN9S) – Aaron Feb 28 '20 at 16:25
  • For a variety of approaches highlighting different requirements, see https://stackoverflow.com/questions/32960857/how-to-convert-arbitrary-simple-json-to-csv-using-jq – peak Feb 28 '20 at 16:45
  • 1
    @Aaron - using `values` in this way and in this context is asking for trouble. – peak Feb 28 '20 at 20:59
  • @peak I expected it to work in a fashion similar to `keys` and went with it when I saw it worked as expected with the sample. I see now it would ignore `null` values, but are there any other problems to expect? – Aaron Feb 29 '20 at 00:09
  • The possible occurrence of `null` was the main problem I had in mind. – peak Feb 29 '20 at 00:21

1 Answers1

2

Here's a relatively robust jq script for printing the TSV with headers using the key names in the first object:

(.[0] | keys_unsorted) as $keys
| $keys,  (.[] | [.[$keys[]]])
| @tsv  

This of course assumes the -r command-line option.

oguz ismail
  • 1
  • 16
  • 47
  • 69
peak
  • 105,803
  • 17
  • 152
  • 177
  • What if I want to specifies the keys as the default order may not satisfy my need and not all fields in the json file should be printed. – user1424739 Feb 28 '20 at 19:38
  • @user1424739 - you can specify the keys you want by changing the first line in the solution, e.g. `["x","y","z"] as $keys`. – peak Feb 28 '20 at 20:11