Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jq: nested object, extract top-level id and lift a value from internal object

Tags:

json

bash

jq

Given the following xample.json;

[
 {
  "id": 12345678,
  "stuff": { "book": "shelf", "hook": "line", "took": "off", "info-spec": 12 },
  "votes": 23
 },
 {
  "id": 12345679,
  "stuff": { "book": "maker", "hook": "sinker", "took": "pisin", "info-spec": 23 },
  "votes": 1
 }
]

I can extract the id and votes easily:

$ jq '.[] | { id, votes }' xample.json
{
  "votes": 23,
  "id": 12345678
}
{
  "votes": 1,
  "id": 12345679
}

But what would the query look like to extract id and stuff.info-spec? The obvious (to me) syntax doesn't work at all:

$ jq '.[] | { id, stuff.info-spec }' xample.json
error: syntax error, unexpected '.', expecting '}'
.[] | { id, stuff.info-spec }
                 ^
1 compile error

I tried stuff[info-spec] and stuff["info-spec"] as well but, well, I just don't seem to have any idea how this should be done.

The dash in the key name seems to complicate matters even further, but my limited understanding is that I can work around that with double quotes.

$ sed 's/votes/vo-tes/g' xample.json | jq '.[] | { id, "vo-tes" }'

gives the expected output (i.e. similar to above without the dash in "vo-tes").

I can extract book:

$ jq '.[] | .stuff.book' xample.json

but again cannot figure out the syntax for id and book; but also, I cannot extract info-spec with the same syntax:

$ jq '.[] | .stuff."info-spec"' xample.json
error: syntax error, unexpected QQSTRING_START, expecting IDENT
.[] | .stuff."info-spec"
             ^
1 compile error

If I take out the quotes, the error message is (predictably) different:

$ jq '.[] | .stuff.info-spec' xample.json
error: spec is not defined
.[] | .stuff.info-spec
                  ^^^^
1 compile error

But hey, this works:

$ jq '.[] | .stuff["info-spec"] ' xample.json
12
23

My desired output for this example, then, is

{
  "info-spec": 12,
  "id": 12345678
}
{
  "info-spec": 23,
  "id": 12345679
}

I've looked at the FAQ and the jq Cookbook but I can't seem to find anything about a syntax for "lifting" an item from within an object inside another object.

like image 641
tripleee Avatar asked Dec 19 '14 08:12

tripleee


2 Answers

interesting, the issue is indeed the "-" character and this works for me:

jq '.[] | { id, "info-spec": .stuff."info-spec" }' xample.json
{
  "id": 12345678,
  "info-spec": 12
}
{
  "id": 12345679,
  "info-spec": 23
}

yet your jq does not seem to like that syntax as it broke on the following and mine does not:

jq '.[] | .stuff."info-spec"' xample.json
12
23

I use:

jq --version
jq-1.4

edit: looks like a version issue with <1.4 indeed: https://github.com/stedolan/jq/issues/38

like image 167
Hans Z. Avatar answered Nov 11 '22 00:11

Hans Z.


I managed to figure it out.

$ jq '.[] | { id, "info-spec": .stuff["info-spec"] }' xample.json
{
  "info-spec": 12,
  "id": 12345678
}
{
  "info-spec": 23,
  "id": 12345679
}

The key here seems to be to use the newkey: .complex["key"] notation for lifting.

like image 14
tripleee Avatar answered Nov 11 '22 00:11

tripleee