简体   繁体   中英

Escape json tags in bash script or jq

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"
}
]

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"

Update after clarifying edit of the question: It has become clear that you want to transform the value into a string. jq has the tostring filter for that, the program thus becomes:

to_entries | map({
    Name: .key,
    Value: (.value | tostring),
    Type: "String",
    Overwrite: true
})

Note that this will not keep the line breaks and indents, but formats the JSON object in a "compact" way. Let us know if that's a problem.

$ jq 'to_entries | map({
    Name: .key,
    Value: (.value | tostring),
    Type: "String",
    Overwrite: true
})' <<JSON
{
  "a": 1,
  "b": 2,
  "c": {
    "id": "9ee ...",
    "parent": "abc..."
  }
}
JSON
[
  {
    "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
  }
]

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

To JSON-encode data from within jq you can use the tojson (or @json ) builtins.

Also, to get the actual type of some data, there is the type function.

Maybe you are trying to accomplish something like this:

# Convert the the YAML file into JSON
json="$(yq -j "$file_name")"

# Transform the JSON data into desired format
jq 'to_entries | map({Name: .key} + (.value | {
      EncodedValue: tojson,
      OriginalType: type,
      Overwrite:    true
    }))' <<< "$json" > "$new_file_name"

Checking the contents of the new file would now give you something like:

[
  {
    "Name": "a",
    "EncodedValue": "1",
    "OriginalType": "number",
    "Overwrite": true
  },
  {
    "Name": "b",
    "EncodedValue": "2",
    "OriginalType": "number",
    "Overwrite": true
  },
  {
    "Name": "c",
    "EncodedValue": "{\"id\":\"9ee ...\",\"parent\":\"abc...\"}",
    "OriginalType": "object",
    "Overwrite": true
  }
]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM