3

I have a valid JSON values that is generated from using JQ from a string,

# key1:value1,key2:value2 --> {"key1":"value1","key2":"value2"}
input='key1:value1,key2:value2'
json=$( jq -Rc 'split(",") | map( split(":") | {(.[0]): .[1]}) add |' <<<"$input" )
echo $json

This works perfectly fine but now I want to convert the json to string without escaping the double quotes of each key and value and just need to add single quotes at the end.

# {"key1":"value1","key2":"value2"} --->  '{"key1":"value1","key2":"value2"}'

I tried the tostring function but it escapes all double quotes

strJson=$(jq tostring <<< "$json")
echo $strJson
Faisal
  • 403
  • 4
  • 18
  • `print -v quoted "'%s'" "$json"; echo "$quoted"` – Inian Jul 25 '22 at 08:46
  • @Inian I'm running this in Azure Pipeline shell, It says that "Unable to initialize device PRN". – Faisal Jul 25 '22 at 09:12
  • 1
    BTW, `echo $anything` is buggy; it should always be `echo "$anything"`. See [I just assigned a variable but `echo $variable` shows something else!](https://stackoverflow.com/questions/29378566/i-just-assigned-a-variable-but-echo-variable-shows-something-else) – Charles Duffy Jul 25 '22 at 10:08
  • By the way -- what's the specific context for "surround by single quotes"? Often single quotes are correct for literal values but wrong for values stored in variables. For example, it's correct to write json='{"foo": "bar"}'`, but those quotes aren't actually part of your stored value; instead, they're directives to the shell about how to parse that value. – Charles Duffy Jul 27 '22 at 12:43
  • @CharlesDuffy I have to pass this JSON as a String to Helm charts via the '--set-string' flag via cli. So the context it that the users will enter key,value pairs in the parameters of a pipeline, those would be converted to JSON and then passed as string without escaping double quotes to helm charts. Helm charts themselves are quite bad at handling JSON values for variables though, they will be instead introducing a --set-json flag in the coming release that would be a lot more handy – Faisal Aug 01 '22 at 20:06
  • @Faisal, when you run `--set-json '{"key": "value"}'` on the command line, the single quotes *aren't part of the value*. Instead, they're part of the shell instructions on how to parse the value. If you have `{"key": "value"}` in a shell variable, you just use `--set-json "$variable"` to pass it through exactly as-is, no single-quotes needed. – Charles Duffy Aug 02 '22 at 00:07

1 Answers1

4

Add @json to encode the result as JSON, then add @sh to escape the string for Shell compatibility, and replace the -c option to -r for raw output:

jq -Rr 'split(",") | map( split(":") | {(.[0]): .[1]}) | add | @json | @sh' <<<"$input"
'{"key1":"value1","key2":"value2"}'

Demo


Addendum: This solution follows the expressed requirement to wrap a JSON document in single quotes without escaping the double quotes inside. However, as it is/was unclear for what or how the resulting data is being used, and to shed more light on the ongoing discussion thereof, storing the plain JSON result in a shell variable and using it as an argument to another program may as well be what the OP was trying to achieve:

#!/bin/bash

input='key1:value1,key2:value2'
json="$(jq -Rc 'split(",") | map( split(":") | {(.[0]): .[1]}) | add' <<<"$input")"

program --set-argument "$json"
pmf
  • 24,478
  • 2
  • 22
  • 31
  • 1
    `@sh` is appropriate for values being `eval`ed by a shell; that's not the case here. – Charles Duffy Jul 25 '22 at 10:09
  • @CharlesDuffy It *may* not be the case here. But for my understanding, OP simply didn't elaborate on what the desired format is being used for, so I figured `@sh` may be more robust for a general/unknown case than simply quoting the JSON result with `@json "'\''\(.)'\''"`. – pmf Jul 25 '22 at 10:26
  • See comments on the question. The OP clearly is trying to replace a shell command line where one uses `--set-json '{"json-value": "goes-here"}'`; but those single quotes are syntactic, not literal. – Charles Duffy Aug 02 '22 at 00:09