Convert JSON to headed TSV - json

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

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.

Related

How to convert Json Objects to table using keys as rows and nested keys as columns [duplicate]

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
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.

Nested JSON with variable keys to TSV using jq

I have the following nested JSON file labs.json with variable keywords (lab001, lab002, etc.) which I would like to convert into a TSV using jq:
{
"lab001": {
"tags": {
"T1": [],
"T2": ["k26","e23"],
"T3": ["s92"]
},
"code": "8231"
},
"lab002": {
"tags": {
"T1": ["t32","y55"],
"T2": ["q78"],
"T3": ["b24"]
},
"code": "9112"
}
}
The resulting table should look like:
ID
T1
T2
T3
lab001
k26,e23
s92
lab002
t32,y55
q78
b24
Currently I am using a rather pedestrian approach by pasting two calls of jq and doing some cleanup with tr:
paste <(jq -r 'keys_unsorted | #csv' labs.json | tr ',' '\n') <(jq -r '.[].tags | map(tostring) | #tsv' labs.json) | tr -d '[]"'
Is there any more elegant way to get this done purely with jq?
Join elements of each tag by commas, put resulting strings into an array with the lab ID as the first element, and pipe it to the #tsv filter like so:
keys_unsorted[] as $id | [$id, (.[$id].tags[] | join(","))] | #tsv
Online demo

Transforming a list containing key/value strings with jq

So, I basically have a file test.json
[
"Name=TestName",
"Tag=TestTag"
]
Which I'd like to transform into
[
{
"ParameterKey": "Name",
"ParameterValue": "TestName",
},
{
"ParameterKey": "Tag",
"ParameterValue": "TestTag",
}
]
With jq. Any idea?
You don't need to use split() call twice but just once and access the results directly with the Array/Object Value Iterator: .[] and specifying the index inside
jq -n '[ inputs[] | split("=") | {ParameterKey: .[0], ParameterValue: .[1]} ]'
You can try JQ Play
I tried with the following jq. It should work as long as you are sure of the format of the array.
[.[] | {ParameterKey: split("=")[0], ParameterValue: split("=")[1]}]
If you are using from terminal, you can use the following option
cat test.json | jq '[.[] | {ParameterKey: split("=")[0], ParameterValue: split("=")[1]}]'

How to flatten JSON array values as CSV using JQ

I have a JSON file containing application clients and their associated application features:
{
"client-A": [
"feature-x"
],
"client-B": [
"feature-x",
"feature-y"
],
"client-C": [
"feature-z"
],
"client-D": [
"feature-x",
"feature-z"
],
...
}
I'm trying to turn this into the following CSV:
client,feature
client-A,feature-x
client-B,feature-x
client-B,feature-y
client-C,feature-z
client-D,feature-x
client-D,feature-z
What's an easy way using jq to get this done?
Not sure whether this is the most efficient way of doing it, but you can convert use the following pipeline:
<yourfile.json jq -r 'to_entries | .[] | { key: .key, value: .value[] } | [ .key, .value ] | #csv'
to_entries converts the structure into "key value" pairs, which can then be operated on. The { key: .key, value: .value[] } bit will convert the array into multiple rows...

How to use jq #CSV filter to generate a csv file with values from different json levels

I have a JSON file from the Spotify API that lists all the songs on a specific album. The file is organized as follows:
.
.name
.tracks.items
.tracks.items[]
.tracks.items[].artists
.tracks.items[].artists[].name
.tracks.items[].duration_ms
.tracks.items[].name
I'm using jq to create a csv with the following information: song's artist, song's title, and song's duration. I can do this using the following syntax:
jq -r '.tracks.items[] | [.artists[].name, .name, .duration_ms] | #csv' myfile.json
Output:
"Michael Jackson","Wanna Be Startin' Somethin'",363400
"Michael Jackson","Baby Be Mine",260666
...
However, I would like to also add the value under .name (which represents the name of the album the songs are from) to every row of my csv file. Something that would look like this:
"Thriller","Michael Jackson","Wanna Be Startin' Somethin'",363400
"Thriller","Michael Jackson","Baby Be Mine",260666
...
Is it possible to do this using the #csv filter? I can do it by hand by hardcoding the name of the album like this
jq -r '.tracks.items[] | ["Thriller", .artists[].name, .name, .duration_ms] | #csv' myfile.json
But I was hoping there might be a nicer way to do it.
EDIT:
Here's what the file looks like:
{
"name": "Thriller",
"tracks": {
"items": [
{
"artists": [
{
"name": "Michael Jackson"
}
],
"duration_ms": 363400,
"name": "Wanna Be Startin' Somethin'"
},
{
"artists": [
{
"name": "Michael Jackson"
}
],
"duration_ms": 260666,
"name": "Baby Be Mine"
}
]
}
}
See the "Variable / Symbolic Binding Operator" section in jq's documentation
jq -r '
.name as $album_name ### <- THIS RIGHT HERE
| .tracks.items[]
| [$album_name, .artists[].name, .name, .duration_ms]
| #csv
' myfile.json