Come aggiorno un singolo valore in un documento json usando jq?


104

Mi scuso se ho trascurato qualcosa di molto ovvio; Ho appena trovatojq e sto cercando di usarlo per aggiornare un valore JSON senza influire sui dati circostanti.

Vorrei reindirizzare un curlrisultato jq, aggiornare un valore e reindirizzare il JSON aggiornato a un file curl -X PUT. Qualcosa di simile a

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

Finora l'ho hackerato insieme usando sed, ma dopo aver guardato alcuni esempi |=dell'operatore in jqsono sicuro che non ne ho bisogno.

Ecco un esempio JSON: come utilizzerei jqper impostare "local": false, preservando il resto del JSON?

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

Risposte:


126

Impostare i valori di un oggetto utilizzando l' =operatore. |=d'altra parte viene utilizzato per aggiornare un valore. È una differenza sottile ma importante. Il contesto dei filtri cambia.

Poiché stai impostando una proprietà su un valore costante, utilizza l' =operatore.

.shipping.local = false

Tieni presente che quando si imposta un valore a una proprietà, non deve necessariamente esistere. Puoi aggiungere facilmente nuovi valori in questo modo.

.shipping.local = false | .shipping.canada = false | .shipping.mexico = true

10
Questo campione non va bene per il valore normale. Quindi, se è necessario modificare il valore normale, è necessario aggiungerlo ", ad esempio .shipping.local = "new place". Quindi l'intero comando sarà curl http://example.com/shipping.json | jq '.shipping.local = "new place"'. Altrimenti, otterrai strani errori.
BMW

8
@ BMW cosa? Va benissimo qui. Qualsiasi valore json valido è valido, questo è solo il letterale false. I valori non devono essere stringhe.
Jeff Mercado

@ BMW con cui l'OP vuole impostarlo false. Cosa c'è che non va?
SOFe

17

Aggiorna un valore (imposta .foo.bar su "nuovo valore"):

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

Aggiorna un valore utilizzando una variabile (imposta .foo.bar su "hello"):

variable="hello"; jq --arg variable "$variable" '.foo.bar = $variable' file.json

L'ho usato come esempio per rinominare un pacchetto NPM.json tramite shell e ha funzionato al 100%, grazie.
Machado

2
Questo in realtà non sostituisce il contenuto del file. Stampa solo su stdout. Sarà necessario salvare di nuovo stout nel file per rendere persistente la modifica. Vedi stackoverflow.com/a/60744617/1626687
spuder

1

una funzione simile all'operatore | = è map. map sarà adatto per evitare il requisito di un filtro precedente per l'array ...

immagina che i tuoi dati siano un array (molto comune per questo esempio)

[
  {
    "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": "$"
      }
    }
  }
]

quindi è necessario considerare l'array nel codice come:

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

o per usare la funzione map che è predisposta per funzionare in ogni elemento dell'array come

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

Osservazione

Per il bene di coloro che stanno imparando, hai anche fatto degli errori nell'utilizzo di jq, considera solo che "legge" il primo parametro come programma, quindi tutti i comandi desiderati devono essere inclusi nella primissima stringa dopo aver chiamato il programma.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.