55

In jq, how can I convert a JSON to a string with key=value?

From:

{
    "var": 1,
    "foo": "bar",
    "x": "test"
}

To:

var=1
foo=bar
x=test
fedorqui
  • 252,262
  • 96
  • 511
  • 570
gianebao
  • 15,940
  • 3
  • 28
  • 40

4 Answers4

92

You could try:

jq -r 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' test.json

Here's a demo:

$ cat test.json
{
    "var": 1,
    "foo": "bar",
    "x": "test"
}
$ jq -r 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' test.json
foo=bar
var=1
x=test
Jakub Bochenski
  • 2,953
  • 4
  • 31
  • 58
aioobe
  • 399,198
  • 105
  • 792
  • 807
  • 3
    Is there any way i can do this recursively? – gianebao Aug 19 '14 at 07:50
  • There is a recurse function... But I guess you need to say what field to recurse on. Do you have a fixed field you want to recurse on, or just "any value that's an object"? – aioobe Aug 19 '14 at 07:52
  • none in particular. I'll just try a different approach for the recurse. – gianebao Aug 20 '14 at 01:13
  • I found this question looking to convert a json object into an array of key/value pairs -- `to_entries` is exactly what I needed. – mattsilver Mar 13 '17 at 15:05
  • @aioobe is there a way you could capitalize the keys? I tried `\(.key | tr a-z A-Z)` to no avail. – Dane Jordan Feb 11 '19 at 00:37
  • `jq -r 'to_entries|map("\(.key|@uri)=\(.value|@uri)")|join("&")'` gets you a valid query string. – cachius Sep 21 '21 at 10:34
  • To protect the values by quoting them (for use in shell scripts for example), use:`jq -r 'to_entries|map("\(.key)=" + @sh "\(.value|tostring)")|.[]'`. The `@sh` string formatter is available since `jq` version 1.3 . – ack Jan 24 '22 at 09:40
5

Is there any way i can do this recursively?

Here is a function which might do what you want:

# Denote the input of recursively_reduce(f) by $in.
# Let f be a filter such that for any object o, (o|f) is an array.
# If $in is an object, then return $in|f;
# if $in is a scalar, then return [];
# otherwise, collect the results of applying recursively_reduce(f)
# to each item in $in.
def recursively_reduce(f):
  if type == "object" then f
  elif type == "array" then map( recursively_reduce(f) ) | add
  else []
  end;

Example: emit key=value pairs

def kv: to_entries | map("\(.key)=\(.value)");


[ {"a":1}, [[{"b":2, "c": 3}]] ] | recursively_reduce(kv)
#=> ["a=1","b=2","c=3"]

UPDATE: After the release of jq 1.5, walk/1 was added as a jq-defined built-in. It can be used with the above-defined kv, e.g. as follows:

 walk(if type == "object" then kv else . end) 

With the above input, the result would be:

[["a=1"],[[["b=2","c=3"]]]]

To "flatten" the output, flatten/0 can be used. Here is a complete example:

jq -cr 'def kv: to_entries | map("\(.key)=\(.value)");
        walk(if type == "object" then kv else . end) | flatten[]'

Input:

[ {"a":1}, [[{"b":2, "c": 3}]] ]

Output:

a=1
b=2
c=3
peak
  • 88,177
  • 15
  • 123
  • 150
4

Incidentally, building off of @aioobe's excellent answer. If you need the keys to be all upper case you can use ascii_upcase to do this by modifying his example:

jq -r 'to_entries|map("\(.key|ascii_upcase)=\(.value|tostring)")|.[]'

Example

I had a scenario similar to yours but wanted to uppercase all the keys when creating environment variables for accessing AWS.

$ okta-credential_process arn:aws:iam::1234567890123:role/myRole | \
     jq -r 'to_entries|map("\(.key|ascii_upcase)=\(.value|tostring)")|.[]'
EXPIRATION=2019-08-30T16:46:55.307014Z
VERSION=1
SESSIONTOKEN=ABcdEFghIJ....
ACCESSKEYID=ABCDEFGHIJ.....
SECRETACCESSKEY=AbCdEfGhI.....

References

slm
  • 14,096
  • 12
  • 98
  • 116
2

without jq, I was able to export every item in json using grep and sed but this will work for simple cases only where we have key/value pairs

for keyval in $(grep -E '": [^\{]' fileName.json | sed -e 's/: /=/' -e "s/\(\,\)$//"); do
    echo "$keyval"
done

here's a sample response:

❯ for keyval in $(grep -E '": [^\{]' config.dev.json | sed -e 's/: /=/' -e "s/\(\,\)$//"); do
    echo "$keyval"       
done
"env"="dev"
"memory"=128
"role"=""
"region"="us-east-1"
Muhammad Soliman
  • 18,833
  • 5
  • 99
  • 70