Modify a key-value in a json using jq in-place

JsonBashShellJq

Json Problem Overview


I have a json in which I want to modify a particular value but the terminal always displays the json with the modified value but it does not actually change the value in the particular file. Sample json:

{
   name: 'abcd',
   age: 30,
   address: 'abc'
}

I want to change the value of address in the file itself but so far I've been unable to do so. I tried using:

jq '.address = "abcde"' test.json

but it didn't work. Any suggestions?

Json Solutions


Solution 1 - Json

Use a temporary file; it's what any program that claims to do in-place editing is doing.

tmp=$(mktemp)
jq '.address = "abcde"' test.json > "$tmp" && mv "$tmp" test.json

If the address isn't hard-coded, pass the correct address via a jq argument:

address=abcde
jq --arg a "$address" '.address = $a' test.json > "$tmp" && mv "$tmp" test.json

Solution 2 - Json

AFAIK jq does not support in-place editing, so you must redirect to a temporary file first and then replace your original file with it, or use sponge utility from the moreutils package, like that:

jq '.address = "abcde"' test.json|sponge test.json

There are other techniques to "redirect to the same file", like saving your output in a variable e.t.c. "Unix & Linux StackExchange" is a good place to start, if you want to learn more about this.

Solution 3 - Json

Temp files add more complexity when not needed (unless you are truly dealing with JSON files so large you cannot fit them in memory (GB to 100's of GB or TB, depending on how much RAM/parallelism you have)

The Pure bash way.

contents="$(jq '.address = "abcde"' test.json)" && \
echo -E "${contents}" > test.json

Pros

  • No temp file to juggle
  • Pure bash
  • Don't need an admin to install sponge, which is not installed by default
  • Simpler

Cons

  • This works perfectly fine for json because it cannot contain a literal null character. If you were to try this outside the json arena, it would fail when a null is encountered (and you would have to do some encoding/decoding workarounds). Bash variables cannot store literal nulls.

Note: this can not be combined as "one command" (like @codekandis suggested), since redirection sometimes starts before the left hand side (LHS) of an expression is run, and starting redirection before running jq erroneously empties the file, hence two separate commands. It may "seem" to work when you try it, but this is misleading and has a very high probability of failing as soon as the circumstances change.

Update: Added -E option to disable escape characters just in case you are on systems where they are interpreted by default. (Which I've never actually seen)

Solution 4 - Json

Just to add to chepner answer and if you want it in a shell script.

test.json

{
  "name": "abcd",
  "age": 30,
  "address": "abc"
}

script.sh

#!/bin/bash
address="abcde"
age=40

# Strings:
jq --arg a "${address}" '.address = $a' test.json > "tmp" && mv "tmp" test.json
    
# Integers:
jq --argjson a "${age}" '.age = $a' test.json > "tmp" && mv "tmp" test.json

Solution 5 - Json

Example for nested json with changing single and multiple values.

config.json

{
  "Parameters": {
    "Environment": "Prod",
    "InstanceType": "t2.micro",
    "AMIID": "ami-02d8e11",
    "ConfigRegion": "eu-west-1"
  }
}

with the below command, you can edit multiple values.

tmp=$(mktemp)
jq '.Parameters.AMIID = "ami-02d8sdfsdf" | .Parameters.Environment = "QA"' config.json > "$tmp" && mv "$tmp" config.json

with the below command, you can edit single value.

tmp=$(mktemp)
jq '.Parameters.AMIID = "ami-02d8sdfsdf"' config.json > "$tmp" && mv "$tmp" config.json

Solution 6 - Json

this should work

address = aaaaa
echo $(jq --arg a "$address" '.address = ($a)' test.json) > test.json

for whatever reason, without the echo, it makes a bin file and my python script was not able to parse it.

Solution 7 - Json

I didn't like any of the solutions and created the sde utility.

pip install sde

Then you can simply do:

sde address abcde test.json

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionwolfsbaneView Question on Stackoverflow
Solution 1 - JsonchepnerView Answer on Stackoverflow
Solution 2 - JsonzeppelinView Answer on Stackoverflow
Solution 3 - JsonAndyView Answer on Stackoverflow
Solution 4 - JsonRafal KitaView Answer on Stackoverflow
Solution 5 - Jsonmahendra rathodView Answer on Stackoverflow
Solution 6 - JsonDelcroipView Answer on Stackoverflow
Solution 7 - JsonDanila VershininView Answer on Stackoverflow