This question already has answers here:
How to use jq when the variable has reserved characters?
(3 answers)
Closed 4 years ago.
How do I access the value of a JSON attribute that contains a period in it's name on MacOS/ Linux?
For example, I have a JSON object which has a root attribute name containing a period. For example:
{
"foo.bar": {
"one": 1,
"two": "2",
"three": {
"a": "3a",
"b": "3b"
}
}
}
On jqplay.org the filter ."foo.bar" successfully extracts the value of the attribute:
{
"one": 1,
"two": "2",
"three": {
"a": "3a",
"b": "3b"
}
}
However, on MacOS and Linux (jq v1.5) the same input and filter (i.e. jq ."foo.bar" file.json produces no output.
If I add brackets to the filter (i.e. .["foo.bar"]) I get the following:
{
"foo.bar": {
"one": 1,
"two": "2",
"three": {
"a": "3a",
"b": "3b"
}
}
}
{
"one": 1,
"two": "2",
"three": {
"a": "3a",
"b": "3b"
}
}
1
"2"
{
"a": "3a",
"b": "3b"
}
"3a"
"3b"
How can I replicate the behaviour from jqplay.org on MacOS/ Linux so I can access attributes with periods in their names?
OK, figured this out... I needed to wrap the whole filter in single quotes:
jq '."foo.bar"' file.json
In the command line you need to either escape the quotes or enclose the filter in single quotes. Otherwise, the shell thinks the quotes are there to take the string they enclose as a single word.
Assuming your JSON is stored in the file input.json, the command line should be like:
cat input.json | jq .\"foo.bar\"
or:
cat input.json | jq '."foo.bar"'
For this simple filter I recommend using the second way (enclose the filter in apostrophes) because it is easier to read and understand.
Related
Example json:
{
"a": 1,
"c": {
"ca": 1.1
},
"d": {},
"e": [1,2,3],
"f": [
{
"fa": "vf1",
"fb": "vf2",
"fc": [],
"fffs232/232": {
"z": 1
}
},
{
"fa": "vf3",
"fb": "vf4",
"fc": [1.1,2.3],
"fffs232/232": {
"z": 2
}
}
]
}
I want a full path jq expression that gives me the values of "z". Such expression should not explicitly mention "fffs232/232" since that key is dynamic.
Is this possible with jq?
Thanks!
You could use .., e.g. along the lines of:
jq '.. | objects | .z // empty'
If .z can take the value null, then adjust according to your requirements.
If the name is dynamic but the position is known, you can iterate over field candidates using .[] and check if a subfield "z" exists using select and has:
.f[][] | select(has("z")?).z
Demo
Alternatively, if the depths are also unknown, you can traverse the whole document using ..:
.. | select(has("z")?).z
Demo
I want to modify values within a hash. Sometimes the values are simple strings or numbers, and other times they are objects.
I can start with a simple example:
jq -n '{a:"string",b:{k:"k",v:1},c:12}'
which results in
{
"a": "string",
"b": {
"k": "k",
"v": 1
},
"c": 12
}
I want the value of the b key in the hash to get the value of .v below it (I actually want to do things more complex but it works for this example).
My attempt:
jq -n '
{a:"string",b:{k:"k",v:1},c:12} |
with_entries(.value|=if .v? then .v else . end)
'
outputs:
{
"a": null,
"b": 1,
"c": null
}
I see the value of b becomes 1 as expected, but when .v does not exist, it causes the entire value to become null instead of . as I expected.
This does not appear to be specific to the .foo? operation either.
jq -n '
{a:"string",b:{k:"k",v:1},c:12} |
with_entries(.value|=if (.|strings) then . else . end)
'
outputs
{
"a": "string",
"b": null,
"c": null
}
Any idea how I can have complex logic for updating .value ?
.v? only returns null if . is an object that could have a key v, but doesn't; otherwise, it evaluates to no value at all.
$ jq -n '{a:1}.v?'
null
$ jq -n '"foo".v?'
$
With nothing to test, the if-then-else expression also has no value at all, which results in .value being removed from the input to with_entries.
Likewise, .|strings filters out non-string values entirely; it doesn't provide a false or null for each element of . that isn't a string. Any array is true, so the then value is always returned, but only for string-valued values. Otherwise, no value is returned, and .value is again removed.
objects can be used, but on the left of |=, not the right. You want to disregard non-objects from even being updated, rather than trying to replace it with itself if it isn't an object with v.
jq -n '
{a:"string",b:{k:"k",v:1},c:12} |
with_entries((.value|objects) |= if .v then .v else . end)
'
There's no further need for .v?; if you are sure that all objects will have a v key, you can dispense with the if-then-else expression as well.
This should achieve what you expected :
jq -n '{a:"string",b:{k:"k",v:1},c:12}|.b |= .v'
If you want to keep the structure of you script, add object test :
jq -n '
{a:"string",b:{k:"k",v:1},c:12} |
with_entries(.value|=(if type == "object" and .v? then .v else . end))
'
I'm trying to process some JSON with jq. Specifically, I want a particular key, based on its child value. Example, given:
{
"foo": {"primary": true, "blah": "beep"},
"bar": {"primary": false, "blah": "narf"},
"baz": {"primary": false, "blah": "poink"},
}
I want the string "foo", because that is the key whose child value "primary' is true. (I can guarantee that one and only one entry will have primary = true, due to what's generating the JSON.)
So far the best I've been able to manage is:
jq -r '.[] | select(.primary == true)'
But that returns the value of "foo", not the string "foo" itself. Digging through the manual so far I've not found a way to grab the key specifically.
Any pointers you can provide?
You need to "split" your object into an array of entries, e.g.
[
{
"key": "foo",
"value": {
"primary": true,
"blah": "beep"
}
}
//...
]
Then you can filter with .value.primary and map the result with .key:
to_entries | map(select(.value.primary) | .key)
Returns:
[
"foo"
]
Or to get just the first item of the array: (Thanks #nbari)
to_entries | map(select(.value.primary) | .key)[0]
I'm trying to update some objects based on a list of objects. For example I want to turn this:
{
"names": ["a","c"],
"del": {
"a": true,
"b": true,
"c": true
}
}
into this:
{
"names": ["a","c"],
"del": {
"a": false,
"b": true,
"c": false
}
}
So for each object name in .names update its corresponding object in .del
The solution I can up with seems inefficient and I was wondering if there was a better way.
[foreach .names[] as $name (.;.del[$name] = false ; .) ] | last
I think using last is a good indication that you don't care about intermediate values and since foreach1 is described as:
The foreach syntax is similar to reduce, but intended to allow the construction of limit and reducers that produce intermediate results
There is an equivalent reduce:
reduce .names[] as $name (.; .del[$name]=false)
When both are possible, reduce is more efficient in terms of code as communication with other programmers and potential performance. (If the reduce implementation were found to be slower than a pattern with foreach, then jq could reimplement reduce with that pattern.)
I have an expression in JsonPath which outputs me something like the following:
[
"someString"
]
however, this causes my Java code to crash, because I cannot assign it directly to a string. Yes, I could get the first position of the Array in Java, but it would be nicer to directly become this from JsonPath:
{
"someString"
}
I have tried something like {jsonPathExpression}[0], but then I get an empty array... Am I missing something?
Here a Json Sample Code:
{
"products":[
[
"foo",
"bar",
"notthisone",
"456",
"789",
"000"
],
[
"foo",
"bar",
"bingo",
"456",
"!!!!",
"000"
]
]
}
and the path: $.products[?(#[2] == 'bingo')][4]
And please donĀ“t blame the ugly json structure ([] braces after products instead of {}), as you can imagine, it is a remote service which I need to call and want only the necessary data... ;)