Reputation: 1499
If I have a JSON input data:
input.json
{
"metadata": {
"guid": "07f90eed-105d-41b2-bc20-4c20dfb51653"
},
"entity": {
"name": "first"
}
}
{
"metadata": {
"guid": "da187e3a-8db9-49fd-8c05-41f29cf87f51"
},
"entity": {
"name": "second"
}
}
{
"metadata": {
"guid": "6685c3af-5427-4add-8764-7b18ae3c23bb"
},
"entity": {
"name": "third"
}
}
and I want to create from it the following:
{
"first": "07f90eed-105d-41b2-bc20-4c20dfb51653",
"second": "da187e3a-8db9-49fd-8c05-41f29cf87f51",
"third": "6685c3af-5427-4add-8764-7b18ae3c23bb"
}
That is, the input data is a collection of separate JSON objects, each of which has the structure shown. I want the output to be a single JSON object where the key is the .entity.name
and the value is the .metadata.guid
.
I have tried:
jq -r '{.entity.name: .metadata.guid}' input.json
jq -r 'map({(.entity.name): .metadata.guid})' input.json
but these just yields a syntax error. The closest I got was:
jq -r '.entity.name as $name|.metadata.guid as $guid | { ($name) : ($guid) }' input.json
{
"first": "07f90eed-105d-41b2-bc20-4c20dfb51653"
}
{
"second": "da187e3a-8db9-49fd-8c05-41f29cf87f51"
}
{
"third": "6685c3af-5427-4add-8764-7b18ae3c23bb"
}
But, the there are still 3 objects (not 1).
I did get one form to give me what I want, but I suspect there is an easier way to do this:
jq -r '.entity.name as $name|.metadata.guid as $guid | { ($name) : ($guid) }' input.json | jq -s add
{
"first": "07f90eed-105d-41b2-bc20-4c20dfb51653",
"second": "da187e3a-8db9-49fd-8c05-41f29cf87f51",
"third": "6685c3af-5427-4add-8764-7b18ae3c23bb"
}
Any thoughts how how to do this properly?
Upvotes: 3
Views: 1550
Reputation: 92884
With single jq
command:
jq -s '[.[] | { (.entity.name): .metadata.guid }] | add' input.json
-s
(--slurp
) - instead of running the filter for each JSON object in the input, read the entire input stream into a large array and run the filter just once.The output:
{
"first": "07f90eed-105d-41b2-bc20-4c20dfb51653",
"second": "da187e3a-8db9-49fd-8c05-41f29cf87f51",
"third": "6685c3af-5427-4add-8764-7b18ae3c23bb"
}
Upvotes: 7
Reputation: 72336
A simpler way to get three objects is jq '{(.entity.name): .metadata.guid}' input.json
.
Wrapping the key (.entity.name
) into parentheses tells jq
to evaluate it as an expression, not as a string.
This leads to a simpler form of what you already have (using two invocations of jq
):
$ jq '{(.entity.name): .metadata.guid}' input.json | jq -s add
{
"first": "07f90eed-105d-41b2-bc20-4c20dfb51653",
"second": "da187e3a-8db9-49fd-8c05-41f29cf87f51",
"third": "6685c3af-5427-4add-8764-7b18ae3c23bb"
}
Upvotes: 2