Home > Software design >  escape json tags in bash script or jq
escape json tags in bash script or jq

Time:01-08

I have a YAML file which I am converting into JSON files using yq. It generates the following output,

{
  "a" : 1,
  "b" : 2,
  "c" : {
  "id": "9ee ...",
  "parent": "abc..."
  }
}

Then I am creating another JSON based on the above JSON key & value. Please find the below code snippet,

# Extract the properties from the YAML file
json=$(yq -j "$file_name")

# Iterate over the properties
parameters=""
for key in $(echo "${json}" | jq -r 'keys[]'); do

    # Extract the key and value of the property
    value=$(echo "${json}" | jq -r ".$key")
    echo "Adding parameter $key with value $value to SSM"

    # Add the property to the list of parameters
    parameters ="{\"Name\": \"$key\", \"Value\": \"$value\", \"Type\": \"String\", \"Overwrite\": true}"
done

Since the value in the 1st JSON is already JSON so we couldn't able to generate the 2nd JSON which is generating an invalid-JSON error.

Is there any way to escape/stringify the JSON characters in bash script or jq, so that we can able to generate the 2nd JSON?

Any help would be really appreciated.

Actual output:

[
{
"Name": "a",
"Value": "1",
"Type": "String",
"Overwrite": "true"
},
{
"Name": "b",
"Value": "2",
"Type": "String",
"Overwrite": "true"
},
{
"Name": "c",
"Value": "{
      "id": "9ee ...",
      "parent": "abc..."
      }",
"Type": "String",
"Overwrite": "true"
}
]

The above one is not a valid JSON.

Expected output:

[
{
"Name": "a",
"Value": "1",
"Type": "String",
"Overwrite": "true"
},
{
"Name": "b",
"Value": "2",
"Type": "String",
"Overwrite": "true"
},
{
"Name": "c",
"Value": "{\r\n      \"id\": \"9ee ...\",\r\n      \"parent\": \"abc...\"\r\n      }",
"Type": "String",
"Overwrite": "true"
}
]

CodePudding user response:

Why try to emulate jq's behavior with a shell loop (which should generally be avoided) instead of using jq directly?

yq -j "$file_name" | jq 'to_entries | map({
    Name: .key,
    Value: .value,
    Type: "String",
    Overwrite: true
})'

Or directly transform using yq only:

yq 'to_entries | map({
    Name: .key,
    Value: .value,
    Type: "String",
    Overwrite: true
})' -j "$file_name"

CodePudding user response:

This should achieve what's expected :

jq 'to_entries | map({
    Name: .key,
    Value: (.value|if (type == "object")
                   then tojson
                   else tostring
                   end),
    Type: "String",
    Overwrite: true})
' input.json
  • Related