Reputation: 1082
I'm trying to change multiple json values with this line
jq '.two="newval", .three="newval"' my.json
with this is the input
{
"one": {
"val": 1
},
"two": "val",
"three": "val",
"four": "val"
}
but the output is 2 jsons:
{
"one": {
"val": 1
},
"two": "newval",
"three": "val",
"four": "val"
}
{
"one": {
"val": 1
},
"two": "val",
"three": "newval",
"four": "val"
}
How can I change multiple values and output in one item?
Upvotes: 31
Views: 24257
Reputation: 701
This old question is popular on Google and I had a similar need that led to a more concise solution (which I'm not sure if existed at the time of ask). In my case, I needed to assign the same value to multiple keys which fits the example OP gave but it bears warning that this won't work for assigning different values.
Keep the comma operator and pass the combined stream to the assignment:
$ jq '(.two, .three) = "newval"' data.json
{
"one": {
"val": 1
},
"two": "newval",
"three": "newval",
"four": "val"
}
jqPlay example: https://jqplay.org/s/Jx7m-pnl_OQ
I needed to mask sensitive (secret) values in Kubernetes manifests that looked like this:
{
"apiVersion": "v1",
"kind": "Secret",
"metadata": {
"name": "test"
},
"data": {
"foo": "czAwcGVyczNrcml0Cg=="
},
"stringData": {
"baz": "s00pers3krit"
}
}
With a few additional complicating factors:
foo
and baz
sub-keys were arbitrary and unknown ahead of timedata
and stringData
keys could be present.kind == "Secret"
should be masked$ helm template helm/ | yq '( select(.kind == "Secret") | (.data[]?, .stringData[]?) ) = "[Masked]"'
{
"apiVersion": "v1",
"kind": "Secret",
"metadata": {
"name": "secret1"
},
"type": "kubernetes.io/dockerconfigjson",
"data": {
".dockerconfigjson": "[Masked]"
},
"stringData": {
".dockerconfigjson": "[Masked]"
}
}
{
"apiVersion": "v1",
"kind": "Secret",
"metadata": {
"name": "secret2"
},
"type": "kubernetes.io/dockerconfigjson",
"data": {
"baz": "[Masked]"
},
"stringData": {
"quux`": "[Masked]"
}
}
{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"name": "configmap1"
},
"type": "kubernetes.io/dockerconfigjson",
"data": {
"foo": "czAwcGVyczNrcml0Cg==",
"snuffle": "fuzzy"
}
}
[Masked]
to the selected keys:
() = "[Masked]"
.kind == "Secret"
for reassignment:
( select(.kind == "Secret") ) = "[Masked]"
( select(.kind == "Secret") | (., .) ) = "[Masked]"
data
and stringData
of those objects:
( select(.kind == "Secret") | (.data, .stringData) ) = "[Masked]"
.data
but modify all its child key):
( select(.kind == "Secret") | (.data[], .stringData[]) ) = "[Masked]"
( select(.kind == "Secret") | (.data[]?, .stringData[]?) ) = "[Masked]"
jqPlay: https://jqplay.org/s/8SqKgeP1BzN
Upvotes: 4
Reputation: 116750
Simply change the comma to a pipe character and you’re done:
.two="newval" | .three="newval"
"," is for concatenating streams: A,B
will emit A followed by B.
Upvotes: 71
Reputation: 14665
Here is a method which uses + object addition to update multiple members.
. + {two:"newtwo", three:"newthree"}
Sample Run (assumes data in data.json
)
$ jq -M '. + {two:"newtwo", three:"newthree"}' data.json
{
"one": {
"val": 1
},
"two": "newtwo",
"three": "newthree",
"four": "val"
}
Upvotes: 16