¿Cómo actualizo un valor único en un documento json usando jq?

103

Disculpas si he pasado por alto algo muy obvio; Acabo de encontrarlo jqy estoy tratando de usarlo para actualizar un valor JSON sin afectar los datos circundantes.

Me gustaría canalizar un curlresultado jq, actualizar un valor y canalizar el JSON actualizado a un curl -X PUT. Algo como

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

Hasta ahora, lo he pirateado usando sed, pero después de ver algunos ejemplos del |=operador en jq, estoy seguro de que no los necesito.

Aquí hay una muestra de JSON: ¿cómo usaría jqpara configurar "local": false, mientras conservo el resto del JSON?

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

Respuestas:

126

Establece los valores de un objeto utilizando el =operador. |=por otro lado se utiliza para actualizar un valor. Es una diferencia sutil pero importante. El contexto de los filtros cambia.

Dado que está estableciendo una propiedad en un valor constante, use el =operador.

.shipping.local = false

Solo tenga en cuenta que al establecer un valor para una propiedad, no necesariamente tiene que existir. Puede agregar nuevos valores fácilmente de esta manera.

.shipping.local = false | .shipping.canada = false | .shipping.mexico = true
Jeff Mercado
fuente
10
Esta muestra no es buena para el valor normal. Entonces, si necesita cambiar el valor normal, debe agregarlo ", como .shipping.local = "new place". Entonces todo el comando será curl http://example.com/shipping.json | jq '.shipping.local = "new place"'. De lo contrario, obtendrá errores extraños.
BMW
8
@BMW ¿qué? Está perfectamente bien aquí. Cualquier valor json válido es válido, esto resulta ser el literal false. Los valores no tienen por qué ser cadenas.
Jeff Mercado
@BMW el OP quiere configurarlo false. ¿Qué pasa?
SOFe
17

Actualizar un valor (establece .foo.bar en "nuevo valor"):

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

Actualice un valor usando una variable (establece .foo.bar en "hola"):

variable="hello"; jq --arg variable "$variable" '.foo.bar = $variable' file.json
Paul Chris Jones
fuente
Usé esto como un ejemplo para cambiar el nombre de un package.json de NPM a través de shell y funcionó al 100%, gracias.
Machado
2
En realidad, esto no reemplaza el contenido del archivo. Solo imprime en stdout. Deberá guardar stout de nuevo en el archivo para que el cambio persista. Ver stackoverflow.com/a/60744617/1626687
spuder
1

una función similar al operador | = es mapa. map será adecuado para evitar el requisito de un filtro previo para la matriz ...

imagina que tus datos son una matriz (muy común en este ejemplo)

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

por lo tanto, es necesario considerar la matriz en el código como:

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

o utilizar la función de mapa que está diseñada para funcionar en cada elemento de la matriz como

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

Observación

Por el bien de aquellos que están aprendiendo, también cometió algunos errores en el uso de jq, solo considere que "lee" el primer parámetro como el programa, por lo tanto, todos los comandos deseados se incluirán en la primera cadena después de llamar al programa.

Thiago Conrado
fuente