skip to Main Content

I have an existing key.json file that looks like this:
key.json

{
"resstart": 1700839261,
"resend": 1700839965,
"resop": "SUCCESS",
"resurl": "http://xxxx/",
"ressummary": {
  "value": 1,
  "expect": 0,
  "tool": "abc"
 },
}

I need to add the below section in my json under ressummary

"Check": [
   {
       "Check": "["A_DOG","A_CAT", "A_HORSE"]",
       "code": "C/C++"
   }
  ]

So the final json file should look like:

{
"resstart": 1700839261,
"resend": 1700839965,
"resop": "SUCCESS",
"resurl": "http://xxxx/",
"ressummary": {
   "value": 1,
   "expect": 0,
   "tool": "abc"
   "Check": [
     {
        "Check": "["A_DOG","A_CAT", "A_MOUSE", "A_HORSE"]",
        "code": "C/C++"
     }
   ]
 },
}

I am using shell script to generate the above json. My code is:

name="key"
ccheck=("A_DOG" "A_CAT" "A_MOUSE" "A_HORSE")
echo "{"Check": { "Check": "['$ccheck[@]']", "code": "C/C++"}}" >> $name.json
sed -i "s/'/"/g" $name.json
cat $name.json

I am getting the below error:
parse error: jq 1 compile error

Can anyone tell me how I can get the desired json file ? I would like to do this with jq. Is there a better way to do this? I have tried define ccheck as a string and array, but i am not getting the "" and , either.

3

Answers


  1. To achieve the desired result in your JSON file using jq, you’ll need to modify your approach slightly.

    1. Read the existing JSON: First, use jq to read the existing JSON file.
    2. Modify the JSON: Add the new "Check" section under "ressummary". Since you’re dealing with an array of strings and you need to preserve the quotes inside the string, you’ll need to handle this carefully.
    3. Write the modified JSON back: Finally, output the modified JSON back to the file.
    #!/bin/bash
    
    # The name of your JSON file
    name="key.json"
    
    # The array of items for the "Check" key
    ccheck=("A_DOG" "A_CAT" "A_MOUSE" "A_HORSE")
    
    # Convert array to a JSON array of strings
    json_array=$(printf '%sn' "${ccheck[@]}" | jq -R . | jq -s .)
    
    # Use jq to add the new "Check" section under "ressummary"
    jq --argjson arr "$json_array" 
       '.ressummary.Check = [{"Check": $arr | join(","), "code": "C/C++"}]' 
       "$name" > temp.json && mv temp.json "$name"
    
    # Display the updated JSON
    cat "$name"
    
    
    • printf '%sn' "${ccheck[@]}" | jq -R . | jq -s .: This part of the script converts the bash array ccheck into a JSON array. jq -R reads raw strings (one per line) and jq -s slurs them into an array.
    • The jq command then adds this array under the "Check" key in "ressummary". We use join(",") to convert the array into a string representation, which includes the required quotes.
    • The output is written to a temporary file (temp.json) and then renamed to your original file name. This is a safer way to modify files with jq.

    Run this script in the directory where your key.json file is located. It will add the specified section to your JSON file as per your requirement.

    Login or Signup to reply.
  2. Here is my shell with jq

    cat input.json insert.json | jq -s ".[0] * (.[0].ressummary * .[1] | {ressummary:.})"
    
    cat input.json insert.json | jq -s ".[0].ressummary += .[1]|.[0]"
    

    input.json

    {
        "resstart": 1700839261,
        "resend": 1700839965,
        "resop": "SUCCESS",
        "resurl": "http://xxxx/",
        "ressummary": {
            "value": 1,
            "expect": 0,
            "tool": "abc"
        }
    }
    

    insert.json

    {
        "Check": [
            {
                "Check": [
                    "A_DOG",
                    "A_CAT",
                    "A_HORSE"
                ],
                "code": "C/C++"
            }
        ]
    }
    

    The result:

    {
      "resstart": 1700839261,
      "resend": 1700839965,
      "resop": "SUCCESS",
      "resurl": "http://xxxx/",
      "ressummary": {
        "value": 1,
        "expect": 0,
        "tool": "abc",
        "Check": [
          {
            "Check": [
              "A_DOG",
              "A_CAT",
              "A_HORSE"
            ],
            "code": "C/C++"
          }
        ]
      }
    }
    

    Here is explain.

    I am only explain the first statement I given.
    The correct ressummary we need:

    {
    ...
    "ressummary": {
        "value": 1,
        "expect": 0,
        "tool": "abc",
        "Check": [
          {
            "Check": [
              "A_DOG",
              "A_CAT",
              "A_HORSE"
            ],
            "code": "C/C++"
          }
        ]
      }
    }
    
    

    So basically we just merge the insert.json to the ressummary.

    .[0].ressummary * .[1]
    

    using this statement will make a json looks like this.

    {
      "value": 1,
      "expect": 0,
      "tool": "abc",
      "Check": [
        {
          "Check": [
            "A_DOG",
            "A_CAT",
            "A_HORSE"
          ],
          "code": "C/C++"
        }
      ]
    }
    

    And this should be place under the ressummary

    .[0].ressummary * .[1] | {ressummary:.}
    

    Using this statement will get a json looks like this

    {
      "ressummary": {
        "value": 1,
        "expect": 0,
        "tool": "abc",
        "Check": [
          {
            "Check": [
              "A_DOG",
              "A_CAT",
              "A_HORSE"
            ],
            "code": "C/C++"
          }
        ]
      }
    }
    

    then we can merge it to the original input.

    .[0] * (.[0].ressummary * .[1] | {ressummary:.})
    

    use parentheses for priority arithmetic .[0].ressummary * .[1] | {ressummary:.}


    PS: Using -s with jq will make jq read multiple input as array like this:

    [
      {
        "resstart": 1700839261,
        "resend": 1700839965,
        "resop": "SUCCESS",
        "resurl": "http://xxxx/",
        "ressummary": {
          "value": 1,
          "expect": 0,
          "tool": "abc"
        }
      },
      {
        "Check": [
          {
            "Check": [
              "A_DOG",
              "A_CAT",
              "A_HORSE"
            ],
            "code": "C/C++"
          }
        ]
      }
    ]
    

    BUT I STILL RECOMMEND USING PYTHON TO HANDLE THE JSON.

    Login or Signup to reply.
  3. This is how you import data using jq:

    • use --arg varname "value" to have access to a jq variable $varname set to the string value
    • use --args "value1" "value2" … (as last arguments) to set the builtin $ARGS.positional to the string array ["value1", "value2", …]
    • use .ressummary.Check = […] to set the Check field to an array as defined (or .ressummary.Check += […] to append to that array)
    #!/bin/bash
    
    ccheck=("A_DOG" "A_CAT" "A_MOUSE" "A_HORSE")
    code="C/C++"
    jq --arg code "$code" '.ressummary.Check = [{Check: $ARGS.positional, $code}]' 
       key.json --args "${ccheck[@]}"
    
    {
      "resstart": 1700839261,
      "resend": 1700839965,
      "resop": "SUCCESS",
      "resurl": "http://xxxx/",
      "ressummary": {
        "value": 1,
        "expect": 0,
        "tool": "abc",
        "Check": [
          {
            "Check": [
              "A_DOG",
              "A_CAT",
              "A_MOUSE",
              "A_HORSE"
            ],
            "code": "C/C++"
          }
        ]
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search