web-dev-qa-db-fra.com

jq & bash: créer un tableau JSON à partir d'une variable

J'utilise jq pour former un JSON en bash à partir de valeurs variables.

Vous savez comment créer des variables simples

$ VAR="one two three"
$ jq -n "{var:\"$VAR\"}"
{
  "var": "one two three"
}

Mais je ne peux pas encore créer de tableaux. j'ai

$ echo $ARR
one
two
three

et veulent obtenir quelque chose comme

{
  "arr": ["one", "two", "three"]
}

Je parviens seulement à obtenir une sortie brouillée comme

$ jq -n "{arr: [\"$ARR\"]}"
{
  "arr": [
    "one\ntwo\nthree"
  ]
}

Comment former un tableau JSON de manière correcte? jq peut-il jamais faire ça?

[~ # ~] modifier [~ # ~] : Une question a été posée alors qu'il n'y avait que jq 1.3. Maintenant, dans jq 1.4, il est possible de faire directement ce que j'ai demandé, comme @JeffMercado et @peak suggéré, upvote pour eux. N'annulera pas cependant l'acceptation de la réponse de @jbr.

20
Andrey Regentov

jq fait exactement ce que vous lui demandez de faire. jq n'est pas un programme pour générer du JSON, mais un outil pour l'interroger. Ce que vous faites avec le -n switch ne fait que l'utiliser comme une jolie imprimante. Donc, si vous voulez qu'il imprime un objet avec un tableau contenant "un", "deux", "trois", vous devez le générer.

VAR="one two three"
VAR=$(echo $VAR | sed -e 's/\(\w*\)/,"\1"/g' | cut -d , -f 2-)
echo "{var: [$VAR]}"

Mise à jour

Comme Bryan et d'autres mentionnent ci-dessous, il est en effet possible de générer du JSON avec jq, et à partir de la version 1.4, il est même possible de faire ce que l'OP demande directement, voir par exemple réponse de Jeff =.

2
jbr

Dans jq 1.3 et plus, vous pouvez utiliser le --arg VARIABLE VALUE option de ligne de commande:

jq -n --arg v "$VAR" '{"foo": $v}'

C'est à dire., --arg définit une variable à la valeur donnée afin que vous puissiez ensuite utiliser $varname dans votre programme jq, et maintenant vous n'avez plus besoin d'utiliser l'interpolation de variables Shell dans votre programme jq.

EDIT: à partir de jq 1.5 et plus, vous pouvez utiliser --argjson pour passer directement dans un tableau, par ex.

jq -n --argjson v '[1,2,3]' '{"foo": $v}'
24
user2259432

Une fois votre variable chargée, vous devez utiliser le filtre split pour diviser cette chaîne en un tableau.

$ jq -n --arg inarr "${ARR}" '{ arr: $inarr | split("\n") }'
14
Jeff Mercado

La publication d'origine dans ce fil mentionne VAR = "un deux trois". Pour une telle variable, une solution très simple en jq 1.4 est la suivante:

$ jq -n -c -M --arg s "$VAR" '{var: ($s|split(" "))}'
{"var":["one","two","three"]}

(Cela suppose un shell Linux ou Mac ou similaire, et fonctionne avec jq 1.4.)

Si le caractère de séparation est une nouvelle ligne, alors considérez ce TypeScript:

$ s=$(printf "a\nb\nc\n")
$ jq -n -c -M --arg var "$s" '{"var": ($var|split("\n"))}'
{"var":["a","b","c"]}

Notez que la chaîne JSON pour le caractère de nouvelle ligne est "\n" (ne pas "\\n").

Un troisième cas d'intérêt est lorsque VAR est un tableau bash. Dans ce cas, il peut être acceptable de passer les éléments en utilisant "$ {VAR [@]}", mais en général, il faut se rappeler que l'option "--arg name value" est destinée uniquement à passer des chaînes.

Dans jq> 1.4, les variables Shell exportées peuvent être passées à l'aide de l'objet "env", comme indiqué dans la page de manuel jq en ligne.

7
peak

Vous devez d'abord utiliser -R pour lire les lignes brutes et ensuite vous devez slurp toutes les valeurs avec -s:

$ echo -e "one\ntwo\nthree" | jq -R . | jq -s '{"arr": .}'
{
  "arr": [
    "one",
    "two",
    "three"
  ]
}
3
ceving

Cela a fonctionné pour moi dans jq 1.6:

$ jq -nc '$ARGS.positional' --args 1 2 3
["1","2","3"]

Pour ce cas d'utilisation spécifique, vous pouvez utiliser un tableau et écrire:

$ VAR=(one two three)
$ jq -nc '{var: $ARGS.positional}' --args ${VAR[@]}
{"var":["one","two","three"]}

Vous pouvez également utiliser une chaîne comme celle-ci:

$ VAR="one two three"
$ jq -nc '{var: ($ARGS.positional[0] | split(" "))}' --args $VAR
2
ashanbrown

Vous pouvez utiliser cette syntaxe:

jq --arg keyName "MyVal" '.[]."\($keyName)"[] ./JSONFile.js

pour les données d'entrée comme

[{"MyVal":"Value1","MyVal":Value2,"NotMyVal":"Value3"}];

pour obtenir des données analysées à partir de JSON avec des variables.

Cet exemple imprimera:

"Value1"
"Value2"
0
alexglue