Home > Back-end >  Using JQ (or any other .json tool), how can I update an object within an array and return the entire
Using JQ (or any other .json tool), how can I update an object within an array and return the entire

Time:12-04

For example, say I have the following .json blob:

{
    "timestamp": 1234567890,
    "report": "Age Report",
    "results": [
        { "name": "John", "age": 43, "city": "TownA" },
        { "name": "Jane",  "age": 10, "city": "TownB" }
    ]
}

I want to change John's age to 44, and then return the entire blob. I'm looking for the following output:

{
    "timestamp": 1234567890,
    "report": "Age Report",
    "results": [
        { "name": "John", "age": 44, "city": "TownA" },
        { "name": "Joe",  "age": 10, "city": "TownB" }
    ]
}

Additionally, if "age" is not there, I would like to add it.

Thanks!

CodePudding user response:

One way using map and if-then-else:

.results |= map(if .name == "John" then .age = 44 else . end)

JqPlay Demo


Another using select:

( .results[] | select(.name == "John") | .age) |= 44

JqPlay Demo


Both versions rely on:



Additionally, if "age" is not there, I would like to add it.

This requires an additional filter, something like

( .results[] | select(.age | not ))  = { "age": 1 }

Were we use not to select all the objects without .age and then add it.

Combining both filters, would give something like:

( .results[] | select(.age | not ))  = { "age": 1 } | ( .results[] | select(.name == "John") | .age) |= 44

JqPlay Demo

CodePudding user response:

As setting an object's field to a value given does not require its previous content (or its existence even), there is no need for the update operator |=. A simple assignment = does suffice to set (or create) a certain field.

(.results[] | select(.name == "John")).age = 44

This demo contains the input twice, once as given and once with John's .age missing.

  • Related