I want create a more simple json with the same original structure but with one a small sample.
As example, If I have this json:
{
"field1": [
{
"a": "F1A1",
"b": "F1B1"
},
{
"a": "F1A2",
"b": "F1B2"
},
{
"a": "F1A3",
"b": "F1B3"
},
{
"a": "F1A4",
"b": "F1B4"
}
],
"field2": [
{
"a": "F2A1",
"b": "F2B1"
},
{
"a": "F2A2",
"b": "F2B2"
}
],
"field3": [
{
"a": "F3A1",
"b": "F3B1"
},
{
"a": "F3A2",
"b": "F3B2"
}
]
}
I want to get the first array element from the first field. So I was expecting this:
{
"field1": [
{
"a": "F1A1",
"b": "F1B1"
}
],
}
I executed jq "select(.field1[0])" tmp.json but it returns the original json.
Bonus:
As bonus, how to do the same but extracting let's say field1 and elements in the array with a=="F1A1" and a=="F1A4", so will expect?:
{
"field1": [
{
"a": "F1A1",
"b": "F1B1"
},
{
"a": "F1A4",
"b": "F1B4"
}
]
}
reduce the oouter object to your field using {field1}, then map this field to an array containing only the first item:
jq '{field1} | map_values([first])'
{
"field1": [
{
"a": "F1A1",
"b": "F1B1"
}
]
}
To filter for certain items use select:
jq '{field1} | map_values(map(select(.a == "F1A1" or .a == "F1A4")))'
{
"field1": [
{
"a": "F1A1",
"b": "F1B1"
},
{
"a": "F1A4",
"b": "F1B4"
}
]
}
As you can see, select does something different. It passes on its input if the argument evaluates to true. Therefore its output is either all or nothing, never just a filtered part. (Of course, you can use select to achieve specific filtering, as shown above.)
Related
I have a JSON object of the following form:
{
"vars": {
"node1": {"field1": "a", "field2": "b"},
"node2": {"field1": "x", "field2": "y"}
"unrelated": {"blah": "blah"}
},
"nodes": ["node1", "node2"]
}
Now, I can get the fields per node (excluding unrelated) using the following jq expression:
.vars[.nodes[]]
Output:
{
"field1": "a",
"field2": "b"
}
{
"field1": "x",
"field2": "y"
}
My question is, how do I include the vars key as a field in the output, i.e.
{
"node": "node1",
"field1": "a",
"field2": "b"
}
{
"node": "node2",
"field1": "x",
"field2": "y"
}
The name of the key (node in the example) is not important.
Based on this post I found an approximate solution:
.vars | to_entries | map_values(.value + {node: .key})[]
which outputs
{
"field1": "a",
"field2": "b",
"node": "node1"
}
{
"field1": "x",
"field2": "y",
"node": "node2"
}
{
"blah": "blah",
"node": "unrelated"
}
But it still includes the unrelated field which is shouldn't.
Store the nodes array's elements in a variable for reference. Storing the elements rather than the whole array automatically also iterates for the next step. Then, just compose your desired output objects using the nodes array item as object {$node} added to the looked-up object in .vars[$node].
jq '.nodes[] as $node | {$node} + .vars[$node]'
{
"node": "node1",
"field1": "a",
"field2": "b"
}
{
"node": "node2",
"field1": "x",
"field2": "y"
}
Demo
I am using graphiQL to debug my react project's graphql query.
This is my query:
{
testdataJson{
E{
D{
A
B
entries
}
}
}
}
on dataset testdata.json:
{
"E": [
{
"D": [
[
{
"A": "Y1",
"entries": [
"Z1"
]
},
{
"A": "Y2",
"entries": [
"Z2"
]
}
],
[
{
"A": "Y3",
"entries": [
"Z3"
]
},
{
"A": "Y4",
"entries": [
"Z4"
],
"B": true
}
],
[
{
"A": "Y5",
"entries": [
"Z5"
],
"B": true
}
]
]
}
]
}
which gives the error: Cannot query field \"B\" on type \"TestdataJsonED\".
If I change the snippet:
[
{
"A": "Y1",
"entries": [
"Z1"
]
},
{
"A": "Y2",
"entries": [
"Z2"
]
}
],
to
[
{
"A": "Y1",
"entries": [
"Z1"
]
},
{
"A": "Y2",
"entries": [
"Z2"
]
"B": true
}
],
then everything is fine.
This seems weird as I would expect to be able to have lists which don't necessarily contain at least one element with a "B" value. In fact, my JSON data (which I did not create) has this a lot. Alternatively, this is not the cause and I have done something silly!
Cheers,
Edit: related issue - https://github.com/gatsbyjs/gatsby/issues/2392
I need to filter a JSON with a nested strucutre like below.
All objects in array b where attribute x contains a "z" in the value of x should be filtered out. The rest should stay in the file.
{
"a": {
"b": [
{
"c": "1",
"x": "aaa",
},
{
"c": "2",
"x": "aza",
},
{
"c": "7",
"x": "azb",
}
]
},
"d": {
"e": [
"1"
],
"f": [
"2"
]
}
}
Expected output:
{
"a": {
"b": [
{
"c": "1",
"x": "aaa"
}
]
},
"d": {
"e": [
"1"
],
"f": [
"2"
]
}
}
use select with contains:
jq '.a.b|=[.[]|select(.x|contains("z")|not)]' file
I'm currently working through an issue, and can't seem to figure this one out. Here's some data so you know what I'm talking about below:
foo.json
{
"Schedule": [
{
"deviceId": 123,
"reservationId": 123456,
"username": "jdoe"
},
{
"deviceId": 456,
"reservationId": 589114,
"username": "jsmith"
}
],
"serverTime": 1522863125.019958
}
bar.json
[
{
"a": {
"b": "10.0.0.1",
"c": "hostname1"
},
"deviceId": 123
},
{
"a": {
"b": "10.0.0.2",
"c": "hostname2"
},
"deviceId": 456
}
]
foobar.json
{
"Schedule": [
{
"deviceId": 123,
"reservationId": 123456,
"username": "jdoe",
"a": {
"b": "10.0.0.1",
"c": "hostname1"
}
}
},
{
"deviceId": 456,
"reservationId": 789101,
"username": "jsmith",
"a": {
"b": "10.0.0.2",
"c": "hostname2"
}
}
],
"serverTime": 1522863125.019958
}
I'm trying to use jq to do this, and had some help from this post: https://github.com/stedolan/jq/issues/1090
The goal is to be able to combine JSON, using some key as a common point between the documents. The data may be nested any amount of levels.. In this case foo.json has nested data only two levels deep, but needs to be combined with data nested 1 level deep.
Any and all suggestions would be super helpful. I'm also happy to clarify and answer questions if needed. Thank you!
With foobar.jq as follows:
def dict(f):
reduce .[] as $o ({}; .[$o | f | tostring] = $o ) ;
($bar | dict(.deviceId)) as $dict
| .Schedule |= map(. + ($dict[.deviceId|tostring] ))
the invocation:
jq -f foobar.jq --argfile bar bar.json foo.json
yields the output shown below.
Notice that the referents in the dictionary contain the full object (including the key/value pair for "deviceId"), but it's not necessary to del(.deviceId) because of the way + is defined in jq.
Output
{
"Schedule": [
{
"deviceId": 123,
"reservationId": 123456,
"username": "jdoe",
"a": {
"b": "10.0.0.1",
"c": "hostname1"
}
},
{
"deviceId": 456,
"reservationId": 589114,
"username": "jsmith",
"a": {
"b": "10.0.0.2",
"c": "hostname2"
}
}
],
"serverTime": 1522863125.019958
}
I have a particular JSON data which contain float value that I need to conditionally process over an array of JSON. This is an example of one JSON instance:
[
{
"a": "0",
"b": "66.67",
"c": "0",
"d": "0"
},
{
"a": "12.33",
"b": "0",
"c": "60.2",
"d": "19.3"
},
{
"a": "70.0",
"b": "92.67",
"c": "0",
"d": "0"
}
]
and I wish to conditionally select like
cat mydata.json | jq '.[] | select((.a > 50) and (.b > 50))'
and it should sound like
{
"a": "70.0",
"b": "92.67",
"c": "0",
"d": "0"
}
The problem is my original data is a string value and I have no idea how to parse it for a conditional selection.
Simply with jq's tonumber function:
jq '.[] | select((.a|tonumber) > 50 and (.b|tonumber) > 50)' mydata.json
The output:
{
"a": "70.0",
"b": "92.67",
"c": "0",
"d": "0"
}