Comment mettre à jour une valeur unique dans un document json à l'aide de jq?

104

Toutes mes excuses si j'ai oublié quelque chose de très évident; Je viens de le trouver jqet j'essaie de l'utiliser pour mettre à jour une valeur JSON sans affecter les données environnantes.

J'aimerais intégrer un curlrésultat jq, mettre à jour une valeur et diriger le JSON mis à jour vers un fichier curl -X PUT. Quelque chose comme

curl http://example.com/shipping.json | jq '.' field: value | curl -X PUT http://example.com/shipping.json

Jusqu'à présent, je l'ai piraté ensemble en utilisant sed, mais après avoir examiné quelques exemples de l' |=opérateur dans, jqje suis sûr que je n'en ai pas besoin.

Voici un exemple JSON - comment utiliser jqpour définir "local": false, tout en préservant le reste du JSON?

{
  "shipping": {
    "local": true,
    "us": true,
    "us_rate": {
      "amount": "0.00",
      "currency": "USD",
      "symbol": "$"
    }
  }
}
STW
la source

Réponses:

126

Vous définissez les valeurs d'un objet à l'aide de l' =opérateur. |=d'autre part est utilisé pour mettre à jour une valeur. C'est une différence subtile mais importante. Le contexte des filtres change.

Puisque vous définissez une propriété sur une valeur constante, utilisez l' =opérateur.

.shipping.local = false

Notez simplement que lorsque vous définissez une valeur sur une propriété, elle ne doit pas nécessairement exister. Vous pouvez facilement ajouter de nouvelles valeurs de cette façon.

.shipping.local = false | .shipping.canada = false | .shipping.mexico = true
Jeff Mercado
la source
10
Cet échantillon n'est pas bon pour la valeur normale. Donc, si vous avez besoin de modifier la valeur normale, vous devez l'ajouter ", par exemple .shipping.local = "new place". Donc, toute la commande sera curl http://example.com/shipping.json | jq '.shipping.local = "new place"'. Sinon, vous obtiendrez des erreurs étranges.
BMW
8
@BMW quoi? C'est parfaitement bien ici. Toute valeur json valide est valide, il s'agit simplement du littéral false. Les valeurs ne doivent pas nécessairement être des chaînes.
Jeff Mercado
@BMW l'OP veut le définir avec false. Qu'est-ce qui ne va pas?
SOFe
17

Mettre à jour une valeur (définit .foo.bar sur "nouvelle valeur"):

jq '.foo.bar = "new value"' file.json

Mettez à jour une valeur à l'aide d'une variable (définit .foo.bar sur "hello"):

variable="hello"; jq --arg variable "$variable" '.foo.bar = $variable' file.json
Paul Chris Jones
la source
J'ai utilisé cela comme exemple pour renommer un package.json NPM via shell et cela a fonctionné à 100%, merci.
Machado
2
Cela ne remplace pas réellement le contenu du fichier. Il imprime uniquement sur stdout. Vous devrez sauvegarder stout dans le fichier pour que la modification persiste. Voir stackoverflow.com/a/60744617/1626687
spuder
1

une fonction similaire à l'opérateur | = est map. map conviendra pour éviter l'exigence d'un filtre précédent pour le tableau ...

imaginez que vos données sont un tableau (très courant pour cet exemple)

[
  {
    "shipping": {
      "local": true,
      "us": true,
      "us_rate": {
        "amount": "1.00",
        "currency": "USD",
        "symbol": "$"
      }
    }
  },
  {
    "shipping": {
      "local": true,
      "us": true,
      "us_rate": {
        "amount": "1.00",
        "currency": "USD",
        "symbol": "$"
      }
    }
  }
]

il est donc nécessaire de considérer le tableau dans le code comme:

http://example.com/shipping.json | jq '.[] | .shipping.local = "new place"' | curl -X PUT http://example.com/shipping.json

ou pour utiliser la fonction de carte conçue pour fonctionner dans chaque élément du tableau comme

http://example.com/shipping.json | jq 'map(.shipping.local = "new place")' | curl -X PUT http://example.com/shipping.json

Observation

Pour ceux qui apprennent, vous avez également fait des erreurs dans l'utilisation de jq, considérez simplement qu'il "lit" le 1er paramètre comme programme, donc toutes les commandes souhaitées doivent être incluses dans la toute première chaîne après l'appel du programme.

Thiago Conrado
la source