Re-organize json using jq - json

I want to re-organize a json using jq.
My json is like:
[
{
"id": "id1",
"name": "Robin"
},
{
"id": "id2",
"name": "John"
},
{
"id": "id3",
"name": "Jane"
}
]
I want to have an output as :
[
{
"Robin": "id1"
},
{
"John": "id2"
},
{
"Jane": "id3"
}
]
How to achieve this?
Thanks in advance

Yu need:
cat data1.jtxt | jq 'to_entries|map({(.value.name):(.value.id)})'
My output:
[
{
"Robin": "id1"
},
{
"John": "id2"
},
{
"Jane": "id3"
}
]

I cannot understand how was this command so difficult to find
[.[] | {(.id):.name}] | add
gives you:
{
"id1": "Robin",
"id2": "John",
"id3": "Jane"
}
If you want to keep the "object separation" just remove the | add
This question somehow led me to it.

Related

Using jq to search for a value based on a key located deep in json file

I am new to jq and I'm trying to use it to search for a value in a json file based on a key that is located deep in the json structure. Here is a sample of my json file:
{
"data": {
"inventory": {
"location": "remote",
"list": {
"content": [
{
"item": {
"name": "minivan"
},
"owner": {
"id": "12345",
"state": "CA"
}
},
{
"item": {
"name": "sedan"
},
"owner": {
"id": "67890",
"state": "AZ"
}
}
]
}
}
}
}
An example of search that I'm trying to do is:
select item.name where owner.id = "67890"
and the expected output would be:
item.name = "sedan"
I'm trying to run the following:
jq '.[] | select .owner.id = "67890" | .item.name' json
and it generates an error:
jq: error: select/0 is not defined at <top-level>, line 1:
.[] | select .owner.id = "67890" | .item.name
jq: 1 compile error
Any pointers on how to do this in jq would be much appreciated!
Thanks!
First, you have to "navigate" to where you want to make the query. This seems to be an array.
.data.inventory.list.content
[
{
"item": {
"name": "minivan"
},
"owner": {
"id": "12345",
"state": "CA"
}
},
{
"item": {
"name": "sedan"
},
"owner": {
"id": "67890",
"state": "AZ"
}
}
]
Demo
Next, let's iterate over that array's items, which gives us a stream of objects.
.[]
{
"item": {
"name": "minivan"
},
"owner": {
"id": "12345",
"state": "CA"
}
}
{
"item": {
"name": "sedan"
},
"owner": {
"id": "67890",
"state": "AZ"
}
}
Demo
From these objects we select those that match your criteria.
select(.owner.id == "67890")
{
"item": {
"name": "sedan"
},
"owner": {
"id": "67890",
"state": "AZ"
}
}
Demo
Finally, we extract the value you're interested in.
.item.name
"sedan"
Demo
Everything combined in a jq call would be:
jq '.data.inventory.list.content[] | select(.owner.id == "67890").item.name'
"sedan"
Demo
This output is still valid JSON document (containing nothing but a JSON string). If you want to process the output as raw text, use the --raw-output (or -r) option:
jq -r '.data.inventory.list.content[] | select(.owner.id == "67890").item.name'
sedan
Demo
Here's a solution that avoids having to "navigate" to the right place, and which is also quite close to your SQL-like query:
..
| objects
| select(.owner and
(.owner|type=="object" and .id == "67890"))
.item.name
or more succinctly:
..|objects|select(.owner.id? == "67890").item.name

extract values from JSON using jq

I have a JSON object that looks like this:
{
"Accounts": [
{
"Id": "1",
"Name": "Joe",
"Zip": "11111"
},
{
"Id": "2",
"Name": "Jack",
"Zip": "22222"
}
]
}
I am trying to write a jq query that gives me this:
[
{
"Id": "1",
"Name": "Joe"
},
{
"Id": "2",
"Name": "Jack"
}
]
How can I do that? Thanks.
jq '.Accounts | map({ Id, Name })'
Will produce
[
{
"Id": "1",
"Name": "Joe"
},
{
"Id": "2",
"Name": "Jack"
}
]
as you can try online using this demo.
.Accounts selects the Accounts key
map() will apply the following for each object [docs]
Create object with Id and Name key [docs]
Demo https://jqplay.org/s/v01P2gDVc8
You can do
[.Accounts[] | {Id, Name}]

How to extract this string with JQ

I have a JSON file like this :
{
"filter": [
{
"id": "id_1",
"criteria": {
"from": "mail1#mail.com"
},
"action": {
"addLabelIds": [
"Label_1"
],
"removeLabelIds": [
"IMPORTANT",
"SPAM"
]
}
},
{
"id": "id_2",
"criteria": {
"from": "mail2#mail.com"
},
"action": {
"addLabelIds": [
"Label_2"
],
"removeLabelIds": [
"IMPORTANT",
"SPAM"
]
}
}
]
}
I would like to extract id value only where from = mail2#mail.com
I have tried this but does not work :
jq '.filter[] | select(.criteria.from | test("mail2#mail.com"; "i")) | .id'
Have you got any idea?
Thanks
L.
thanks to #Charles Duffy
solution:
select(.criteria.from == "mail2#mail.com")

Getting unique values from nested Array using jq

Trying to get unique values stored in items array for each group. somehow it's always mixed...
My JSON looks like this:
{
"start": 1534425916,
"stop": 1535030716,
"groups": [
{
"group": "transmission",
"data": {
"events": 665762,
},
"items": [
{
"item": "manualni",
"data": {
"events": 389158,
}
},
{
"item": "automaticka",
"data": {
"events": 276604,
}
}
]
},
{
"group": "vat",
"data": {
"events": 671924,
},
"items": [
{
"item": "ne",
"data": {
"events": 346221,
}
},
{
"item": "ano",
"data": {
"events": 325703,
}
}
]
}
]
}
Desired result is the following:
{
"id": "transmission",
"value": [
"manualni",
"automaticka",
]
}
{
"id": "vat",
"value": [
"ne",
"ano"
]
}
Tried with this filter on command line:
| jq '{id: .groups[].group, value: [.groups[].items[].item]}'
Which results in the above mentioned mixed up result:
{
"id": "transmission",
"value": [
"manualni",
"automaticka",
"ne",
"ano"
]
}
{
"id": "vat",
"value": [
"manualni",
"automaticka",
"ne",
"ano"
]
}
Any idea how to receive the uniquified values here? Thanks in advance!
This gets the desired result. I think the manual entry under .[] explains why it works.
jq '.groups[] | {"id": .group, "value": [.items[].item]}'

Selecting multiple conditionals in JQ

I've just started using jq json parser, is there anyway to choose multiple select?
I have this:
cat file | jq -r '.Instances[] | {ip: .PrivateIpAddress, name: .Tags[]}
| select(.name.Key == "Name")'
And I need to also include the .name.Key == "Type"
This is the JSON:
{
"Instances": [
{
"PrivateIpAddress": "1.1.1.1",
"Tags": [
{
"Value": "Daily",
"Key": "Backup"
},
{
"Value": "System",
"Key": "Name"
},
{
"Value": "YES",
"Key": "Is_in_Domain"
},
{
"Value": "PROD",
"Key": "Type"
}
]
}
]
}
And this is the current output:
{
"ip": "1.1.1.1",
"name": "System"
}
{
"ip": "2.2.2.2",
"name": "host"
}
{
"ip": "3.3.3.3",
"name": "slog"
}
Desired output:
{
"ip": "1.1.1.1",
"name": "System",
"type": "PROD"
}
{
"ip": "2.2.2.2",
"name": "host",
"type": "PROD"
}
{
"ip": "3.3.3.3",
"name": "slog",
"type": "PROD"
}
What is the right way to do it? Thanks.
There's no "right" way to do it, but there are approaches to take that can make things easier for you.
The tags are already in a format that makes converting to objects simple (they're object entries). Convert the tags to an object for easy access to the properties.
$ jq '.Instances[]
| .Tags |= from_entries
| {
ip: .PrivateIpAddress,
name: .Tags.Name,
type: .Tags.Type
}' file