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

34,649

Solution 1

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.

Solution 2

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

Share:
34,649
tripleee
Author by

tripleee

I prefer to be referred to as "they". If you are looking for something to vote on, I'm looking for **votes (ideally upvotes, natch) on the tail end** of my answers on Stack Overflow. Look at the lowest-scoring answers; downvotes as well as upvotes appreciated to help me decide what to keep, and what to kill. I'm also thinking my attempt to explain the concept of current working directory to beginners could deserve a few upvotes. The following isn't mine, unfortunately. The image is a clickable link to an archived gist of the original tweet which is now deleted.

Updated on May 24, 2021

Comments

  • tripleee
    tripleee almost 3 years

    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.

  • tripleee
    tripleee over 9 years
    I'm still on 1.2 it seems.