Skip to content

Instantly share code, notes, and snippets.

@joar
Last active March 18, 2024 16:06
Show Gist options
  • Star 83 You must be signed in to star a gist
  • Fork 22 You must be signed in to fork a gist
  • Save joar/776b7d176196592ed5d8 to your computer and use it in GitHub Desktop.
Save joar/776b7d176196592ed5d8 to your computer and use it in GitHub Desktop.
Add a field to an object with JQ
# Add field
echo '{"hello": "world"}' | jq --arg foo bar '. + {foo: $foo}'
# {
# "hello": "world",
# "foo": "bar"
# }
# Override field value
echo '{"hello": "world"}' | jq --arg foo bar '. + {hello: $foo}'
{
"hello": "bar"
}
# {
# "hello": "bar"
# }
# Concat and add
echo '{"hello": "world"}' | jq --arg foo bar '. + {foo: ("not" + $foo)}'
# {
# "hello": "world",
# "foo": "notbar"
# }
@dhackney
Copy link

dhackney commented Sep 9, 2017

The third example, "# Concat and add" , does not produce the output shown in the example:

# {
#   "hello": "world",
#   "foo": "notbar"
# }

This is the actual output:
$ echo '{"hello": "world"}' | jq --arg foo bar '. + {hello: ("not" + $foo)}'

{
"hello": "notbar"
}

tested on:
jq --version: jq-1.5-1-a5b5cbe
and
jq --version: jq-1.5

@arno01
Copy link

arno01 commented Jul 3, 2018

This does:

$ echo '{"hello": "world"}' | jq --arg foo bar '. + {foo: ("not" + $foo)}'
{
  "hello": "world",
  "foo": "notbar"
}

@davidmaxwaterman
Copy link

davidmaxwaterman commented Jul 30, 2019

I have json which is an object containing a property that is an array, and I want to create another property with the same value as an existing property, without changing anything else. eg:

$ echo '{ "text": [ "a": "b" ], "tours": [ "id": 42 ] }' | jq '...'
{
  "text": [
    "a": "b"
  ],
  "tours": [
    "id": 42,
    "tour_id": 42
  ]
}

So far, I've come up with:

  jq '.tours[] | .tour_id = .id'

which duplicates the tours id property to tour_id, but I lose all the top level properties, not to mention the output is no longer JSON.

Any ideas?

@chrisharm
Copy link

Try using * instead of +

$ echo '{"hello": {"value": "world"}}' | jq --arg foo bar '. * {"hello": {foo: ("not" + $foo)}}'
{
  "hello": {
    "value": "world",
    "foo": "notbar"
  }
}

@davidmaxwaterman
Copy link

That's great, thanks :) FWIW, I think I ended up using a cli tool called 'underscore', which allowed me to run plain old js code.

@kylebarron
Copy link

To add a key to a nested object, you can use .key +=:

echo '{"hello": {"value": "world"}}' | jq '.hello += {other_key: "new_val"}'
{
  "hello": {
    "value": "world",
    "other_key": "new_val"
  }
}

@nickboldt
Copy link

Thanks for this! used it to quickly enable experimental features in docker, so I can start playing with buildx inside a VM:

# enable client experimental features like buildx (multiarch)
cat ~/.docker/config.json | jq '. + {experimental: "enabled"}' > ~/.docker/config.json2; mv -f ~/.docker/config.json{2,}
docker buildx 

Ref: https://docs.docker.com/buildx/working-with-buildx/#build-multi-platform-images

@fogfish
Copy link

fogfish commented Jul 1, 2020

A few more examples to insert json:

echo '{"hello": "world"}' | jq --argjson json '{"foo": "bar"}' '. + {foo: $json}'

{
  "hello": "world",
  "foo": {
    "foo": "bar"
  }
}

and same but with files

cat template.json | jq --argjson json "`<snippet.json`" '. + {foo: $json}'

@zrhoffman
Copy link

To add a key to a nested object, you can use .key +=:

echo '{"hello": {"value": "world"}}' | jq '.hello += {other_key: "new_val"}'
{
  "hello": {
    "value": "world",
    "other_key": "new_val"
  }
}

If you are only adding or modifying a single value, there is no need to merge JSON. Same output as above:

echo '{"hello": {"value": "world"}}' | jq '.hello.other_key = "new_val"'

@bacharya
Copy link

bacharya commented Aug 6, 2021

Example for adding an element to an array:

$ echo '[ {"data1":"A"}, {"data2":"B"} ]' | jq --arg val True '.[] += {uppercase: $val}'
[
  {
    "data1": "A",
    "uppercase": "True"
  },
  {
    "data2": "B",
    "uppercase": "True"
  }
]

@aborruso
Copy link

aborruso commented Feb 25, 2023

Hi,
I have this input

{
"a":{"fieldA":2,"fieldB":"foo"},
"b":{"fieldA":2,"fieldB":"foo"}
}

And I would like for each key, to add its value inside the related json object

{
"a":{"fieldA":2,"fieldB":"foo","key":"a"},
"b":{"fieldA":2,"fieldB":"foo","key":"b"}
}

If I run this

<input.json jq  '[.|keys[] as $key | .[] + {key: $key}]'

I obtain something similar, but I have the cartesian product

[
  {
    "fieldA": 2,
    "fieldB": "foo",
    "key": "a"
  },
  {
    "fieldA": 2,
    "fieldB": "foo",
    "key": "a"
  },
  {
    "fieldA": 2,
    "fieldB": "foo",
    "key": "b"
  },
  {
    "fieldA": 2,
    "fieldB": "foo",
    "key": "b"
  }
]

How to avoid it?

Thank you

@MaxNanasy
Copy link

@aborruso This seems to work:

jq 'to_entries | map( { (.key) : (.value + { key: .key }) }) | add'

@aborruso
Copy link

aborruso commented Jun 2, 2023

thank you @MaxNanasy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment