Как преобразовать объект JSON в key = value в jq?
В jq, как я могу преобразовать JSON в строку с key=value
?
From:
{
"var": 1,
"foo": "bar",
"x": "test"
}
To:
var=1
foo=bar
x=test
Ответы
Ответ 1
Вы можете попробовать:
jq -r 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' test.json
Вот демо:
$ 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
Ответ 2
Есть ли способ сделать это рекурсивно?
Вот функция, которая может делать то, что вы хотите:
# 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;
Пример: emit key = value пары
def kv: to_entries | map("\(.key)=\(.value)");
[ {"a":1}, [[{"b":2, "c": 3}]] ] | recursively_reduce(kv)
#=> ["a=1","b=2","c=3"]
UPDATE: после выхода jq 1.5, walk/1 был добавлен как встроенный jq-встроенный. Его можно использовать с вышеописанным kv, например. следующим образом:
walk(if type == "object" then kv else . end)
С приведенным выше результатом результат будет:
[[ "= 1" ], [[[ "Ь = 2", "с = 3" ]]]]
Чтобы "сгладить" выход, можно использовать flatten/0. Вот полный пример:
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}]] ]
Вывод:
a=1
b=2
c=3
Ответ 3
Я знаю, что jq
очень популярен здесь, но могу ли я посоветовать взглянуть на Xidel?
Xidel - это анализатор HTML/XML/JSON (с использованием CSS, XPath, XQuery, JSONiq и шаблонных шаблонов), но он может делать гораздо больше. Это работа гения, и если вы спросите меня настоящий швейцарский нож в этой категории!
Для отдельных объектов это довольно просто:
$ echo '{"var":1,"foo":"bar","x":"test"}' | \
xidel -s - -e '$json()'
var
foo
x
$ echo '{"var":1,"foo":"bar","x":"test"}' | \
xidel -s - -e '
for $x in $json()
return
concat(
$x,
"=",
$json($x)
)
'
var=1
foo=bar
x=test
Для более продвинутых JSON проще всего сгладить весь JSON (хотя декларация пространства имен необходима!):
$ echo '[{"a":1},[[{"b":2,"c":3}]]]' | \
xidel -s - --xmlns:jnlib="http://jsoniq.org/function-library" -e 'jnlib:flatten($json)'
{
"a": 1
}
{
"b": 2,
"c": 3
}
$ echo '[{"a":1},[[{"b":2,"c":3}]]]' | \
xidel -s - --xmlns:jnlib="http://jsoniq.org/function-library" -e '
let $a:=jnlib:flatten($json) return
$a() ! concat(
.,
"=",
$a(.)
)
'
#or
$ echo '[{"a":1},[[{"b":2,"c":3}]]]' | \
xidel -s - --xmlns:jnlib="http://jsoniq.org/function-library" --xquery '
let $a:=jnlib:flatten($json)
for $x in $a()
return
concat(
$x,
"=",
$a($x)
)
'
a=1
b=2
c=3
Ответ 4
Кстати, построение @aioobe отличный ответ. Если вам нужно, чтобы все клавиши были в верхнем регистре, вы можете использовать ascii_upcase
, изменив его пример:
jq -r 'to_entries|map("\(.key|ascii_upcase)=\(.value|tostring)")|.[]'
ПримерExample
У меня был сценарий, похожий на ваш, но я хотел прописать все ключи в верхнем регистре при создании переменных среды для доступа к 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.....
Ссылки