I have a json object that has an unknown number of variables, like this:
{
"var1": 123,
"var2": 456,
"var3": 789
}
How can I automatically convert it to form the following string?
'var1=123,var2=456,var3=789'
Note, I am looking for a solution that doesn't require installing jq.
3 Answers 3
If you don't care about the order of the object members:
$ perl -CO -MJSON::PP -l -0777 -ne '
$j = decode_json($_);
print join ",", map("$_=$j->{$_}", keys %$j)' your-file
var3=789,var2=456,var1=123
perl comes pre-installed on most systems, and JSON::PP is one its built-in modules.
Or if your system has python3:
PYTHONIOENCODING=utf-8 python3 -c '
import json, sys;
_ = json.load(sys.stdin);
print(",".join(map(lambda i: "%s=%s" % i, _.items())))' < your-file
(the order should be preserved as python3's dictionaries contrary to perl's hashes do keep track of an order of keys).
With a less tamed input such as:
{
"var-\"x\"": 1e-2,
"var=v,v": "\n",
"var\uD83E\uDDD9": null
}
They give
var=v,v=
,var-"x"=0.01,var🧙=
And
var-"x"=0.01,var=v,v=
,var🧙=None
Respectively, while mlr --ijson cat
gives:
var-"x"=1e-2,var=v,v=
,var🧙=null
And jq -r 'to_entries|map("\(.key)=\(.value)")|join(",")'
gives:
var-"x"=0.01,var=v,v=
,var🧙=null
(though neither jq
nor mlr
are generally installed by default).
-
Any reason why you're not just sorting the keys, as in
print join ",", map"$_=$j->{$_}", sort keys %$j
?kos– kos2024年10月13日 08:49:36 +00:00Commented Oct 13, 2024 at 8:49 -
@kos, sounds like the
var1
,var2
in the sample are just placeholders for the actual values. While sorting the keys lexically here (which could also be done using thecanonical
JSON:PP option) would happen to restore the original order in the sample, it wouldn't in the general case.Stéphane Chazelas– Stéphane Chazelas2024年10月13日 09:16:07 +00:00Commented Oct 13, 2024 at 9:16 -
Ok, I see the point, thanks (obviously you know and just got confused in the comment but for others:
canonical
only works while encoding, once the keys are stored into a hash the order is lost no matter what, sosort
ing would be needed in order to sort the values in the output)kos– kos2024年10月13日 09:37:43 +00:00Commented Oct 13, 2024 at 9:37 -
@kos, ah yes, sorry,
canonical
wouldn't help indeed as we're not encoding. Thanks for the correction.Stéphane Chazelas– Stéphane Chazelas2024年10月13日 09:52:24 +00:00Commented Oct 13, 2024 at 9:52
If it will always be this simple, something like this might work
tr : = | tr -d '{}"\n ' | sed -e "s/^/'/" -e "s/$/'/"
In parts:
- translate
:
to=
- remove all other extra characters including punctuation, spaces, newlines
- add single quote at start and end
-
What if the variables are strings, which might contain
{}
etc?Vilinkameni– Vilinkameni2024年10月13日 06:33:29 +00:00Commented Oct 13, 2024 at 6:33 -
@Vilinkameni This is not the case in my application. There will be no special characters like that in the strings. The answer provided works perfectly for me.teeeeee– teeeeee2024年10月13日 07:51:42 +00:00Commented Oct 13, 2024 at 7:51
-
This is the simplest answer. It's not the best answer. OP said it would always be simple, so there are a lot of cases this won't work for. I like the other answers. I'm disappointment (but not surprised) there isn't a shorter answer.user10489– user104892024年10月13日 14:42:59 +00:00Commented Oct 13, 2024 at 14:42
One option to do this with awk
will looks like:
awk '!/{/ && !/}/ {gsub("\"","");gsub(":","=");gsub(" ","");printf "%s",0ドル}' input_file
This command expect {
and }
to be the only symbols on the line and the rest of the format to be strict
If you want to have new line at the end you can use command:
awk '!/{/ && !/}/ {gsub("\"","");gsub(":","=");gsub(" ","");printf "%s",0ドル} END {printf "\n"}' input_file
{ }
, then pairs of quoted string with no spaces, an:
, one space, numbers and a comma?jq
is a versatile tool - see e.g. stackoverflow.com/questions/32960857/… for some possibilities.mlr --ijson cat input.json
.jq
:docker run -i --rm ghcr.io/jqlang/jq -r 'to_entries | map("\(.key)=\(.value)") | "'\''\(join(","))'\''"' <file