There is an array of json object, using jq how to check if an object exists if so returns the true else false
I tried this but getting error
cat fruits.json | jq '.fruits[]| sort_by(.version)'
I would like to sort by decending order and output the price of the most recent version.
{
"fruits": [
{
"name": "banana",
"color": "yellow",
"price": 0.51,
"version": 1
},
{
"name": "banana",
"color": "yellow",
"price": 0.52,
"version": 2
}
]
}
cat fruits.json | jq '.fruits | sort_by(-.version)[0].price'
produces:
0.52
You need try like:
.fruits |= sort_by(.version)
Example: https://jqplay.org/s/ntjioYhKWq
Reference sort by keys
Related
myres.json
[
{
"id": "id_1",
"name": "default",
},
{
"id": "id_2",
"name": "name2",
},
{
"id": "id_3",
"name": "name3",
}
]
I waanted to get only name whose id = 3
I am able to filter out the object using yq following command
yq -r '.[] | select(.id == "id_3" )' myres.json
and output is
{
"id": "id_3",
"name": "name3",
}
I tried with with_entries, from_entries but no luck.
Thanks in advance !!
I am using kislyuk/yq 2.14.1 version
As Per #Inian, I made few changes in query as follows according to my requirements.
yq -r '.[] | select(.id=="id_2").name' s.txt
I am just playing with jq. Please check the following outputs.
% FRUITS='[
{
"name": "apple",
"color": "green",
"price": 1.2
},
{
"name": "banana",
"color": "yellow",
"price": 0.5
},
{
"name": "kiwi",
"color": "green",
"price": 1.25
}
]'
% echo $FRUITS
% echo $FRUITS | jq .
% echo $FRUITS | jq '[.[].color] | unique'
[
"green",
"yellow"
]
% echo $FRUITS | jq 'map(.color) | unique'
[
"green",
"yellow"
]
% echo $FRUITS | jq '. | map(has("name"))'
[
true,
true,
true
]
% echo $FRUITS | jq '[.[] | has("name")]'
[
true,
true,
true
]
Here, jq '[.[].color] | unique' give the same output as jq 'map(.color) | unique'
jq '[.[] | has("name")]' give the same output as jq '. | map(has("name"))'
I am not understanding what is the purpose and difference of the map function.
There's absolutely no difference between [ .[] | ... ] vs map( ... ). You can see this in jq's source.
Languages often provide syntactical shortcuts to make certain tasks simpler than by using general tools. This is known as syntactic sugar.
While map is not a special syntax, the same concept applies. It's a nice way to do something that's commonly needed.
It also imports a well-known concept to jq. While map originated in functional programming languages, it has been adopted by a very large number of languages (sometimes under a different name).
Lisp: maplist, mapcar
Perl: map
JavaScript: Array.prototype.map
Python: map
C#: Enumerable.Select
C++: std::transform
etc
I have JSON coming from an external application, formatted like so:
{
"ticket_fields": [
{
"url": "https://example.com/1122334455.json",
"id": 1122334455,
"type": "tagger",
"custom_field_options": [
{
"id": 123456789,
"name": "I have a problem",
"raw_name": "I have a problem",
"value": "help_i_have_problem",
"default": false
},
{
"id": 456789123,
"name": "I have feedback",
"raw_name": "I have feedback",
"value": "help_i_have_feedback",
"default": false
},
]
}
{
"url": "https://example.com/6677889900.json",
"id": 6677889900,
"type": "tagger",
"custom_field_options": [
{
"id": 321654987,
"name": "United States,
"raw_name": "United States",
"value": "location_123_united_states",
"default": false
},
{
"id": 987456321,
"name": "Germany",
"raw_name": "Germany",
"value": "location_456_germany",
"default": false
}
]
}
]
}
The end goal is to be able to get the data into a TSV in the sense that each object in the custom_field_options array is grouped by the parent ID (ticket_fields.id), and then transposed such that each object would be represented on a single line, like so:
Ticket Field ID
Name
Value
1122334455
I have a problem
help_i_have_problem
1122334455
I have feedback
help_i_have_feedback
6677889900
United States
location_123_united_states
6677889900
Germany
location_456_germany
I have been able to export the data successfully to TSV already, but it reads per-line, and without preserving order, like so:
Using jq -r '.ticket_fields[] | select(.type=="tagger") | [.id, .custom_field_options[].name, .custom_field_options[].value] | #tsv'
Ticket Field ID
Name
Name
Value
Value
1122334455
I have a problem
I have feedback
help_i_have_problem
help_i_have_feedback
6677889900
United States
Germany
location_123_united_states
location_456_germany
Each of the custom_field_options arrays in production may consist of any number of objects (not limited to 2 each). But I seem to be stuck on how to appropriately group or map these objects to their parent ticket_fields.id and to transpose the data in a clean manner. The select(.type=="tagger") is mentioned in the query as there are multiple values for ticket_fields.type which need to be filtered out.
Based on another answer on here, I did try variants of jq -r '.ticket_fields[] | select(.type=="tagger") | map(.custom_field_options |= from_entries) | group_by(.custom_field_options.ticket_fields) | map(map( .custom_field_options |= to_entries))' without success. Any assistance would be greatly appreciated!
You need two nested iterations, one in each array. Save the value of .id in a variable to access it later.
jq -r '
.ticket_fields[] | select(.type=="tagger") | .id as $id
| .custom_field_options[] | [$id, .name, .value]
| #tsv
'
Docker Engine API returns container name with / appended
{
"Id": "8dfafdbc3a40",
"Names": [
"/boring_feynman"
],
"Image": "ubuntu:latest",
"ImageID": "d74508fb6632491cea586a1fd7d748dfc5274cd6fdfedee309ecdcbc2bf5cb82",
"Command": "echo 1",
"Created": 1367854155,
"State": "Exited",
"Status": "Exit 0",
"Ports": [{
"PrivatePort": 2222,
"PublicPort": 3333,
"Type": "tcp"
}],
"Labels": {
"com.example.vendor": "Acme",
"com.example.license": "GPL",
"com.example.version": "1.0"
},
"SizeRw": 12288,
"SizeRootFs": 0,
"HostConfig": {
"NetworkMode": "default"
},
"NetworkSettings": {
"Networks": {}
},
"Mounts": [{
"Name": "fac362...80535",
"Source": "/data",
"Destination": "/data",
"Driver": "local",
"Mode": "ro,Z",
"RW": false,
"Propagation": ""
}]
}
I want to remove the slash so the response can be used as a table in JQ:
jq -r '(["Names","Image"] | (., map(length*"-"))), (.[] | [.Names, .Image]) | #tsv'
Currently, when I run the above, I get:
jq: error (at <stdin>:1): array (["/boring_feynman"]) is not valid in a csv row
The problem is not because of / in the .Names field, but in your expression. For filters like #csv or #tsv to work, the values need to be in a scalar format and in an array. But your expression .Name in of type array.
So basically you are passing this result to the #tsv function
[
[
"/boring_feynman"
],
"ubuntu:latest"
]
instead of
[
"/boring_feynman",
"ubuntu:latest"
]
So modifying your filter, you can do below for the JSON in question.
jq -r '(["Names","Image"] | (., map(length*"-"))), ([.Names[], .Image]) | #tsv'
or if you still want to remove the /, use gsub() function
jq -r '(["Names","Image"] | (., map(length*"-"))), ([ (.Names[] | gsub("^/";"")), .Image]) | #tsv'
I am trying to use jq to solve this problem.
Suppose I have the following object
{
"listA": [
{
"id": "12345",
"code": "001"
}
]
"listB": [
{
"id": "12345",
"prop": "AABBCC"
}
]
}
In reality my two lists are longer, but the id isn't repeated within each list.
How may I combine the two lists into a single list where each item is an object with the non-id properties for the given id are collected into a single object?
For example, from the object above, I'd like the following:
{
"listC" : [
{
"id": "12345",
"code": "001",
"prop": "AABBCC"
}
]
}
A simple way would be to concatenate the arrays, group the elements by id and map each group into a single object using add;
jq '.listA+.listB | group_by(.id) | map(add)' test.json
If there may be more than two arrays you need to merge in the file, you could instead use flatten to concatenate all of them.
Test case below
# cat test.json
{
"listA": [
{ "id": "12345", "code": "001" },
{ "id": "12346", "code": "002" }
],
"listB": [
{ "id": "12345", "prop": "AABBCC" }
]
}
# jq 'flatten | group_by(.id) | map(add)' test.json
# or
# jq '.listA+.listB | group_by(.id) | map(add)' test.json
[
{
"id": "12345",
"code": "001",
"prop": "AABBCC"
},
{
"id": "12346",
"code": "002"
}
]
Using group_by entails a sort, which is unnecessary, so if efficiency is a concern, then an alternative approach such as the following should be considered:
INDEX(.listA[]; .id) as $one
| INDEX(.listB[]; .id) as $two
| reduce ($one|keys_unsorted[]) as $k ($two; .[$k] += $one[$k])
| {listC: [.[]] }