jq query not working in expected behaviour - json

{
"data": {
"AWS_ACCESS_KEY_ID": "topsecret",
"AWS_SECRET_ACCESS_KEY": "s3cr3t"
},
"metadata": {
"created_time": "2022-09-16T06:49:11.45818Z",
"deletion_time": "",
"destroyed": false,
"version": 23
}
}
I've above data and I want my input as:
"data": {
"AWS_ACCESS_KEY_ID": "topsecret",
"AWS_SECRET_ACCESS_KEY": "s3cr3t"
}
jq query like this jq .data file.json is only giving me output like this:
{
"AWS_ACCESS_KEY_ID": "topsecret",
"AWS_SECRET_ACCESS_KEY": "s3cr3t"
}
Please help.

Are you sure you want invalid json? You can preserve the key if you enclose it in curly braces, e.g.:
jq '{ data }'
Output:
{
"data": {
"AWS_ACCESS_KEY_ID": "topsecret",
"AWS_SECRET_ACCESS_KEY": "s3cr3t"
}
}
Note that the above is a shorthand for { "data": .data }

Related

How can I print multiple values in one line by `jq`?

I have json data like below:
{
"Items": [
{
"id": {
"S": "c921e4eb-5958-424a-ae3a-b9cada0d9481"
},
"type": {
"S": "transaction.1612878877726"
}
},
{
"id": {
"S": "355057f0-4327-49c7-979f-5a27410d81ba"
},
"type": {
"S": "transaction.1612345630260"
}
},
{
"id": {
"S": "664dc02f-0ad8-484a-98a5-a403beea775b"
},
"type": {
"S": "transaction.1612164919232"
}
},
...
]
}
I'd like to print the value id and type in one line per item from the Items array, e.g.
c921e4eb-5958-424a-ae3a-b9cada0d9481, transaction.1612878877726
355057f0-4327-49c7-979f-5a27410d81ba, transaction.1612345630260
...
I tried cat file | jq '.Items[].id.S, .Items[].type.S' but it prints id and type in separate lines. How can I achieve it with jq?
I would just use string manipulation, either adding 3 strings :
jq --raw-output '.Items[] | .id.S + ", " + .type.S' file
or using string interpolation :
jq --raw-output '.Items[] | "\(.id.S), \(.type.S)"' file
You can try it here.

Creating a new element in an json object using jq

Is there a way to create a new element in an existing json object using jq? Example below:
Let's say I have this json object and would like to add a new element to foo:
json='{
"id": "<id>>",
"name": "<name>",
"properties": {
"State": "<state>",
"requests": [],
"foo": [
{
"id": "<id1>",
"bar1": [
{
"baz1": "*"
}
]
},
{
"id": "<id2>",
"bar2": [
{
"baz2": "*"
}
]
}
]
}
}'
This command works to do that:
json2=$($json1 | jq '.properties.foo += [ { "id": "<id3>", "bar3": [ { "baz3": "*"} ] } ]')
However, running that same command without a preexisting foo element fails (example array below):
json3='{
"id": "<id>>",
"name": "<name>",
"properties": {
"State": "<state>",
"requests": []
}
}'
Is there a way in jq to create that element in the json object if one already does not exist?
Thanks!
There is nothing wrong with your jq program, which can be seen by running:
jq '.properties.foo += [ { "id": "<id3>", "bar3": [ { "baz3": "*"} ] } ]' <<< "$json3"
It looks like the problem is with your invocation but since it's not clear what $json1 is, I'll just guess that the above is sufficient for you to resolve the issue.

Create new JSON value out of strings extracted from another

I have a json file with the following input
{
"Arg":"room=Rhasspy rhasspyName",
"Results": [
{
"Name":"TV",
"Internals": { },
"Readings": { },
"Attributes": { "rhasspyName": "TV" }
},
{
"Name":"dyTest01",
"Internals": { },
"Readings": { },
"Attributes": { "rhasspyName": "radio" }
},
{
"Name":"enoAcPC01",
"Internals": { },
"Readings": { },
"Attributes": { "rhasspyName": "pc" }
} ],
"totalResultsReturned":3
}
With jq '.Results | .[] | .["Attributes"] | .rhasspyName' -r I can get a list like
TV
radio
pc
How can I take this input and create a new json looking like
{"Devices":["TV","radio","pc"]}
Put them into an array and pair that with Devices key in an object.
$ jq '{Devices:[.Results[].Attributes.rhasspyName]}' file
{
"Devices": [
"TV",
"radio",
"pc"
]
}
To create a new file with that JSON value, redirect JQ's stdout to a file, like:
jq '{Devices:[.Results[].Attributes.rhasspyName]}' file > newfile

How to prevent escaping when adding JSON object with jq?

I am working with jq and I am trying to add a new JSON object to a new key to an existing file.
I have the following JSON file, foobarbaz.json :
{
"example":{
"name": "stackOverflowQuestion"
}
}
I want to add a new entry under example, so to get the following output in foobar.json
{
"example": {
"name": "stackOverflowQuestion",
"new": {
"newfield": {
"key": "value"
}
}
}
}
I am using the following commands in the terminal:
$ tempvar='{"newfield":{"key":"value"}}'
$ cat foobarbaz.json | jq '.example.new=env.tempvar' > foobar.json
However, the output in foobar.json is somewhat unexpected:
{
"example": {
"name": "stackOverflowQuestion",
"new": "{\"newfield\":{\"key\":\"value\"}}"
}
}
Why does jq wrap the curly brackets with quotes, and why does it escape the double quotes?
Use fromjson to convert your string (the format all environment variables are in!) to the corresponding data structure, by decoding it as JSON content.
tempvar='{"newfield":{"key":"value"}}' jq '.example.new=(env.tempvar | fromjson)' <<'EOF'
{
"example":{
"name": "stackOverflowQuestion"
}
}
EOF
...emits as output:
{
"example": {
"name": "stackOverflowQuestion",
"new": {
"newfield": {
"key": "value"
}
}
}
}
Use the --argjson option to pass the pre-existing JSON snippet as a variable to the filter.
$ jq --argjson x "$tempvar" '.example.new=$x' foobarbaz.json
{
"example": {
"name": "stackOverflowQuestion",
"new": {
"newfield": {
"key": "value"
}
}
}
}
Note that tempvar isn't strictly necessary and can be dropped, if you are only defining it for use with the filter:
$ jq '.example.new={newfield: {key: "value"}}' foobarbaz.json
{
"example": {
"name": "stackOverflowQuestion",
"new": {
"newfield": {
"key": "value"
}
}
}
}

How to delete array elements that end with 1?

I need to remove all array elements that have the name field ending with 1.
Input:
{
"foo": "bar",
"data": {
"code": "abc123",
"items": [
{
"name": "exp1"
},
{
"name": "exp2"
},
{
"name": "exp11"
}
]
}
}
Desired output:
{
"foo": "bar",
"data": {
"code": "abc123",
"items": [
{
"name": "exp2"
}
]
}
}
My attempt:
jq 'del(.data.items[] | select(.name | endswith("1")))' input
Which results in Invalid path expression.
You can use this jq filter:
jq '.data.items|=map(select(.name|endswith("1")|not))' file
This replace .data.items with the a new array having objects whose names don't end with 1.
Your attempt will work with recent versions of jq (that is, more recent than version 1.5).
Yet another variant (perhaps the most concise robust alternative):
.data.items|=map(select(.name|test("[^1]$")))