Joe
Joe

Reputation: 991

How to replace JSON value with the jq command?

I have this json file:

{
    "orders": "[{\"items\":[{\"itemid\":'',\"quantity\":'',\"price\":'',\"currency\":\"IDR\",\"shopid\":'',\"item_group_id\":null,\"add_on_deal_id\":null,\"checkout\":true}],\"shopid\":''}]",
    "check_voucher_payment_criteria": false,
    "need_wallet_active_info": false
}

I want to replace:

  1. itemid with the value of 321
  2. quantity with the value of 1
  3. price with the value of 100000
  4. shopid with the value of 789

So the result I want is:

{
    "orders": "[{\"items\":[{\"itemid\":321,\"quantity\":1,\"price\":100000,\"currency\":\"IDR\",\"shopid\":789,\"item_group_id\":null,\"add_on_deal_id\":null,\"checkout\":true}],\"shopid\":789}]",
    "check_voucher_payment_criteria": false,
    "need_wallet_active_info": false
}

I tried https://jqplay.org/s/x3IArefkyH:

jq --raw-output '.orders[].items = 321' file.json

But it gave me this error:

jq: error (at <stdin>:4): Cannot iterate over string ("[{\"items\...)
exit status 5

How should I fix it ?

Upvotes: 0

Views: 1745

Answers (3)

peak
peak

Reputation: 116740

The complication here is that your stringified JSON isn't properly stringified. One option would be to make it valid stringified JSON, perform the updates, and stringify it again. In the example, all the occurrences of '' are replaced by JSON values, so it doesn't matter whether this last step (restringification) is done normally (using tojson) or not, so in the following, only the normal stringification is performed.

.orders |= (gsub("''";"\"\"") | fromjson)
| .orders[0].items[0] |= (.itemid = 321 | .quantity=1 | .price = 100000 | .shopid = 789)
| .orders[0].shopid = 789
| .orders |= tojson

Whether that first gsub should be as shown or (gsub("'";"\"") or something else will depend on the processes that produce and consume that mish-mash.

Upvotes: 1

oliv
oliv

Reputation: 13249

In order to let jq understand the the json string inside the orders element, you have to replace the single quote ' in your json file by backslash double quote \".

Then you can use jq to replace the wanted values by transforming the json string to object and back to string:

sed 's/\x27/\\"/g' file | \
jq '.orders|=(fromjson|map(((.items[].itemid|=321)|(.items[].quantity|=1)|(.items[].price|=10000)|(.items[].shopid|=789)))|tojson)'
{
  "orders": "[{\"items\":[{\"itemid\":321,\"quantity\":1,\"price\":10000,   \"currency\":\"IDR\",\"shopid\":789,\"item_group_id\":null,\"add_on_deal_id\":null,\"checkout\":true}],\"shopid\":\"\"}]",
  "check_voucher_payment_criteria": false,
  "need_wallet_active_info": false
}

Upvotes: 1

Anbazhagan IND
Anbazhagan IND

Reputation: 111

Your assinging the orders value as string. that's the reason you won't be able to loop through. remove the double quote when your assiging the orders vlaue like below.

 {
    "orders": [{"items":[{"itemid":"","quantity":"","price":"","currency":"IDR","shopid":"","item_group_id":null,"add_on_deal_id":null,"checkout":true}],"shopid":""}],
    "check_voucher_payment_criteria": false,
    "need_wallet_active_info": false
}

Output

enter image description here

Upvotes: 0

Related Questions