Home > other >  Nested Object Construction JQ
Nested Object Construction JQ

Time:09-29

From 's Types And Values Documentation:

Object Construction

The value can be any expression (although you may need to wrap it in parentheses if, for example, it contains colons), which gets applied to the {} expression's input (remember, all filters have an input and an output).

{foo: .bar}

[ ... ]

Because that is so common, there's a shortcut syntax for it: {user, title}.

So given the following example json

{
    "foo": {
        "bar": {
            "value": 42,
            "valid": true
        },
        "valid": false
    },
    "valid": false
}

If I only want the complete foo object (removing the outer valid key), I can get the desired output by using

{ foo }

Demo


Unfortunately, the documentation doesn't mention any way to get the same behaviour, but for deeper keys, using the example above, getting an output object with just the .foo.bar object would look something like:

{ "foo": { "bar": .foo.bar } }

Demo

Which will generate the following (desired) json output:

{
  "foo": {
    "bar": {
      "value": 42,
      "valid": true
    }
  }
}

Note both the outer valid and the .foo.valid are missing.


Is there any short-cut alternative for the above selector to get the same result?

Ideally I'd use something like:

{ foo.bar }

CodePudding user response:

Not exactly a short-cut alternative, but the path functions can be used for this. This assumes you know the names of the paths beforehand and know they exist

jq -n 'setpath( ["foo", "bar"] ; ( inputs | getpath(["foo", "bar"]) ) )'

The setpath/2 function sets the value on the assigned path indicated in the first argument. The value for the path is set from the original input using getpath/1

You could use the --argjson to pass the path as an array and use it directly as well.

jq -n --argjson p '["foo", "bar"]' 'setpath( $p ; ( inputs | getpath($p) ) )'

CodePudding user response:

Here is (quite literally) a shorter alternative that's also DRYer, though I don't think it's any clearer:

{foo} | .foo |= {bar}
  • Related