Parse JSON data into a variable assignment format - json

I am trying to parse JSON data into variable format
[
{
"Name" : "a",
"Value" : "1"
},
{
"Name" : "b",
"Value" : "2"
},
{
"Name" : "c",
"Value" : "3"
}
]
output should be like
a=1
b=2
c=3
This is what I tried, but it is not giving the expected result:
jq '.[].Value' file.txt

Since you're only printing out two values, it might just be easier to print out the strings directly.
$ jq -r '.[] | "\(.Name)=\(.Value)"' file.txt

You can use the following jq command:
jq -r '.[]|[.Name,.Value]|join("=")' file.json
Output:
a=1
b=2
c=3

Using jq:
jq 'map({(.Name):.Value})|add|.//={}' < data.json
Produces:
{
"a": "1",
"b": "2",
"c": "3"
}
If you have jq version 1.5+, you can use from_entries instead.

This does it
python3 -c 'import json; print("\n".join(["{}={}".format(x["Value"], x["Name"]) for x in json.load(open("file.json"))]))'
result
a=1
b=2
c=3

Related

Using JQ to convert an array of object to list of objects

Let's say I have the following JSON
[
{
name : "A",
value : "1"
},
{
name : "B",
value : "5"
},
{
name : "E",
value : "8"
}
]
and I simply want to to be like
{
name : "A",
value : "1"
},
{
name : "B",
value : "5"
},
{
name : "E",
value : "8"
}
I used jq normal filter so jq'.[]', however I get a list of objects separated by a return as such:
{
name : "A",
value : "1"
}
{
name : "B",
value : "5"
}
{
name : "E",
value : "8"
}
Notice that the commas between the objects have magically vanished. Using reduce would work only if the object is indexed by the name let's say, I used the following:
jq 'reduce .[] as $i ({}; .[$i.name] = $i)'
Anybody did run into a similar situation?
Neither the input as shown nor the desired output is valid as JSON or as a JSON stream, so the question seems questionable, and the following responses are accordingly offered with the caveat that they probably should be avoided.
It should also be noted that, except for the sed-only approach, the solutions offered here produce comma-separated-JSON, which may not be what is desired.
They assume that the quasi-JSON input is in a file qjson.txt.
sed-only
< qjson.txt sed -e '1d;$d; s/^ //'
hjson, jq, and sed
< qjson.txt hjson -j | jq -r '.[] | (.,",")' | sed '$d'
hjson and jq
< qjson.txt hjson -j | jq -r '
foreach .[] as $x (-1; .+1;
if . == 0 then $x else ",", $x end)'

Linux command to print all jsons of same key

I have json as a string "Str"
"{
"A": {
"id": 4
},
"B": {//Something},
"C": {
"A": {
"id": 2
}
},
"E": {
"A": null
},
"F": {//Something}
}"
I wanted all non null values of "A" which can be repeated anywhere in json. I wanted output like all contents of "A"
{"id": 4}
{"id": 2}
Can you please help me with Linux command to get this ?
Instead of line oriented ones use a tool which is capable of parsing JSON values syntax wise. An example using jq:
$ json_value='{"A":{"id":4},"B":{"foo":0},"C":{"A":{"id":2}},"E":{"A":null},"F":{"foo":0}}'
$
$ jq -c '..|objects|.A//empty' <<< "$json_value"
{"id":4}
{"id":2}
.. # list nodes recursively
| objects # select objects
| .A // empty # print A's value if present.

jq: How can a nested object be sliced to include the parent-key hierarchy?

Using Bash and jq, if I have a Bash variable filter F of the form .<key1>.<key2>...<keyN> and I want to slice a Bash variable JSON object O so that the result is just that slice of the object including all keys in F, how can this be done with jq?
For example, suppose:
O='
{
"a":
{
"b":
{
"c": { "p":1 },
"x": 1
},
"x": 2
},
"x": 3
}'
Then, doing:
F='.a.b.c'; jq -r "$F" <<<"$O"
results in:
{
"p": 1
}
But, I want the slice to include parent key hierarchy.
Inelegant Solution
I have come up with a solution, but it involves 2 calls to jq:
F='.a.b.c'; S="$(jq -r "$F" <<<"$O"); jq --null-input -r "$F |= $S"
that results in:
{
"a": {
"b": {
"c": {
"p": 1
}
}
}
}
The solution must work for any valid O and F Bash variable where O stores a JSON object and F is a simple filter of key names only as described above. For example:
F='.a.b'; S="$(jq -r "$F" <<<"$O")"; jq --null-input -r "$F |= $S"
results in:
{
"a": {
"b": {
"c": {
"p": 1
},
"x": 1
}
}
}
Can slicing an object with a key-hierarchy filter be done more simply in jq?
Provided $F is a valid jq path expression (i.e., so that jq -n "$F" works):
jq "$F as \$v | null | $F |= \$v" <<< "$O"
(I included the |= from your solution to show the similarity, but here you could drop the |.)

jq: selecting subset of keys from nested object

Input:
{"success": true, "results": {"a": …, "b": …, "c": …}}
Desired output, given I want to keep b:
{"success": true, "results": {"b": …}}
Things I tried:
$ jq 'del(select(.results.b | not))'
{"success": true, "results": {"a": …, "b": …, "c": …}}
# removes nothing from "results"
$ jq 'with_entries(select(.key == "success" or .key == "results.b"))'
{"success": true}
# nested comparison not understood; returns only "success"
Thanks!
Here is one solution:
.results |= {b}
Sample Run
$ jq -M '.results |= {b}' <<< '{"success":true, "results":{"a": "…", "b": "…", "c": "…"}}'
{
"success": true,
"results": {
"b": "…"
}
}
Try it online at jqplay.org
Another way using nodejs and shell :
Code :
$ node<<EOF
var obj = $(</tmp/file.json);
delete obj.results.a;
delete obj.results.c;
console.log(JSON.stringify(obj));
EOF
OUTPUT :
{"success":true,"results":{"b":"bbb"}}

Extracting element from array in JSON with jq returns "Cannot index array with string"

I have a JSON file:
$ cat ~/tmp/example1.json
[
{
"keyProp": 11111111111111,
"values": [
"VALUE1"
]
},
{
"keyProp": 2222,
"values": [
"VALUE2"
]
}
]
I want to use jq to select values where keyProp==11111111111111. Expected output is 'VALUE2'
I have tried but without result:
cat ~/tmp/example1.json | jq 'select(.keyProp==11111111111111)'
jq: error (at <stdin>:14): Cannot index array with string "keyProp"
To select a block you need to use the expression described in the docs:
select(boolean_expression)
The function select(foo) produces its input unchanged if foo returns
true for that input, and produces no output otherwise.
It’s useful for filtering lists: [1,2,3] | map(select(. >= 2)) will
give you [2,3].
jq '.[] | select(.id == "second")'
Input [{"id": "first", "val": 1}, {"id": "second", "val": 2}]
Output {"id": "second", "val": 2}
So in this case you need to say:
$ jq '.[] | select(.keyProp==11111111111111)' file
{
"values": [
"VALUE1"
],
"keyProp": 11111111111111
}
To extract the list in value, just say so:
$ jq '.[] | select(.keyProp==11111111111111).values' file
[
"VALUE1"
]
You can even extract the first value by using indexes:
$ jq '.[] | select(.keyProp==11111111111111).values[0]' file
"VALUE1"