1

I have a input json file with an array. I need to updated two values (ver & date) in each array element. I could come up with below script but need help. I have hardcoded the ver & date to simplify the script.

input.json

[
  {
    "svcname": "svc1",
    "repo": "https://repo.mycom.org/repocontext/svc1-list",
    "ver": "0.1",
    "date": "2019-11-05"
  },
  {
    "svcname": "svc1",
    "repo": "https://repo.mycom.org/repocontext/svc1-list",
    "ver": "0.1",
    "date": "2019-12-21"
  }
]

Script:

#!/bin/bash
set +x
injson=input.json
updatedjson=$(jq .[] ${injson})

services=$(cat ${injson} | jq '.[] | .svcname' | tr -d \")
i=1
for svc in $services; do 

        echo "==>$svc"
        echo "======> input json=${updatedjson}"
        echo "======> update ver=${i}"
        updatedjson=$(echo ${updatedjson} | jq ". | select( .name ==\"$svc\").ver=\"$i\"" | jq . )
        svcdate="2020-01-$i"
        echo "======> update date=$svcdate"
        updatedjson=$(echo ${updatedjson} | jq ". | select( .name ==\"$svc\").date=\"$svcdate\"" | jq . )
        echo "============================================"
        echo
        i=`expr $i + 1`

done

echo "======= write to file ====="
echo ${updatedjson}
echo ${updatedjson} | jq . > outjson.json

1 Answer 1

2

You are not using the true features of jq. What you shown in a loop, iterating over all the JSON objects can be simply reduced to one reduce() construct that is sort of a for loop in jq given an initial value and runs the filter incrementally

jq 'reduce range(0, length) as $d (.; (.[$d].ver = ($d+1|tostring)) | (.[$d].date = "2020-01-\($d+1)")) '

A brief explanation of how it works

  1. The range expression returns a list with numbers generated from 0 to upto the length of the objects in the array. For your given input it produces 0,1 which is assigned to d
  2. The reduce expression given the input value . the whole JSON, runs by setting the values in each object indexed by $d. So .[$d].ver refers to the ver field in the zeroth index. This is done incrementally till all the objects are processed.
  3. The same way the date field is modified using [$d].date with the value string prefixed (YYYY-MM-) and date is set accordingly.
Sign up to request clarification or add additional context in comments.

1 Comment

Now I am trying to use actual variables (in place of hardcoded values) but running into jq sytax error. === echo ${updatedjson} | jq "reduce range(0, length) as (.; (. | .[] | select( .name ==\"$svc\").version=\"$ver\") | (. | .[] | select( .name ==\"$svc\").date=\"$svcdate\")) " ==== & error is: ==== jq: error: syntax error, unexpected '(', expecting '$' or '[' or '{' (Unix shell quoting issues?) at <top-level>, line 1: ======

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.