How to dynamically update one JSON object and put it back into the original JSON objects variable?
I have one variable with the following JSON data in it.
test='[
{
"Name": "James",
"Mobile": 12345678,
"Gender": "Male",
"Boolean": true,
"Pet": "cat"
},
{
"Name": "John",
"Mobile": 1234567875,
"Gender": "Male",
"Boolean": true,
"Pet": "rat"
},
{
"Name": "Jennifer",
"Mobile": 1234567890,
"Gender": "Female",
"Boolean": true,
"Pet": "Dog"
},
{
"Name": "Julia",
"Mobile": 1234567890,
"Gender": "Female",
"Boolean": true,
"Pet": "Dog"
},
{
"Name": "Jeff",
"Mobile": 9871234567890,
"Gender": "Male",
"Boolean": true,
"Pet": "Fish"
},
{
"Name": "Jones",
"Mobile": 79871234567890,
"Gender": "Female",
"Boolean": true,
"Pet": "Parrot"
}
]'
items=$(echo "$test" | jq -c -r '.[]')
for item in ${items[@]}; do
uName=$(echo $item | jq -r '.Name')
if [ "$uName" == "John" ]; then
echo "$item"
echo " "
modifiedTest=$(echo "$item" | jq '.Name = "Tom"')
modifiedTest=$(echo "$modifiedTest" | jq '.Pet = "rabbit"')
echo "$modifiedTest"
fi
done
Now let's say we have the below second JSON object from the above JSON objects
{
"Name": "John",
"Mobile": 1234567875,
"Gender": "Male",
"Boolean": true,
"Pet": "rat"
}
We have updated the above-picked JSON object fields with below
{
"Name": "Tom",
"Mobile": 1234567875,
"Gender": "Male",
"Boolean": true,
"Pet": "rabbit"
}
Now how can we add/update the above modified JSON object back into the original objects list variable 'test' at the exact position (2nd position in this case) but using a filter of 'Name=John' and in a dynamic way we don't know exact index position of this object using bash scripting?
CodePudding user response:
The tool jq
can be used for JSON-manipulation:
jq '.[1].Name = "Tom" | .[1].Pet = "rabbit"' data.json
This will output the modified file on the console.
Note that in general jq [filter] data.json > data.json
will not work and even when it seems to, overwriting the input file in this way should be avoided. One option would be to use a shell variable:
json_data=$(jq '.[1].Name = "Tom" | .[1].Pet = "rabbit"' data.json)
echo $json_data > data.json
Another option would be to use a temporary file; still another would be to use a utility such as sponge
in moreutils.
Note that your shown file is not valid JSON and so jq will not be able to read it as JSON. To fix it, I have surrounded everything by [
and ]
and removed the extra comma in the John
object.
CodePudding user response:
What if we don't know the exact index position of this object and use a filter of 'Name=John'
< data.json jq '
(map(.Name)| index("John")) as $ix
| (select($ix)
| .[$ix] |= (.Name = "Tom" | .Pet = "rabbit")) // .
' | sponge data.json
But you might want to backup data.json first.