Unable to retrieve key:values, getting error --> jq: error (at <stdin>:0): Cannot index number with string - jq

Unable to extract key:value pairs, tried indexing the block.
<nd.com.citrix.netscaler.json" -X GET https://abcd.com/nitro/v1/config/lbpersistentsessions?args=vserver:puppet-vip.ta10.sd | jq '[.[] ] | .[3] | [.srcip]'
Getting the following error :
jq: error (at <stdin>:0): Cannot index array with string "srcip"
I need to extract the key:values as srcip and destip (see below)
<ion/vnd.com.citrix.netscaler.json" -X GET https://abcd.com/nitro/v1/config/lbpersistentsessions?args=vserver:somevip | jq '[.[] ] | .[3]' | more
[
{
"vserver": "somevip",
"type": "1",
"typestring": "SOURCEIP",
"srcip": “1.1.1.1",
"srcipv6": "::/0",
"destip": "2.2.2.2",
"destipv6": "::/0",
"flags": false,
"destport": 0,
"vservername": “somevip”,
"timeout": "0",
"referencecount": "0",
"persistenceparam": "1.1.1.1"
},
I had to use [.3] to index as the original output is :
<-Type:application/vnd.com.citrix.netscaler.json" -X GET https://abcd.com/nitro/v1/config/lbpersistentsessions?args=vserver:somevip | jq '[.[] ]' | more
[
0,
"Done",
"NONE",
[
{
"vserver": "somevip",
"type": "1",
"typestring": "SOURCEIP",
"srcip": “1.1.1.1”,
"srcipv6": "::/0",
"destip": "2.2.2.2",
"destipv6": "::/0",
"flags": false,
"destport": 0,
"vservername": "somevip",
"timeout": "0",
"referencecount": "0",
"persistenceparam": "1.1.1.1"
},
{
"vserver": "somevip",
"type": "1",
"typestring": "SOURCEIP",
"srcip": "3.3.3.3”,
"srcipv6": "::/0",
"destip": "4.4.4.4”,
"destipv6": "::/0",
"flags": false,
"destport": 0,
"vservername": "somevip",
"timeout": "0",
"referencecount": "0",
"persistenceparam": "1.1.1.1"
},
Also, tried this way and get the error :
<GET https://abcd.com/nitro/v1/config/lbpersistentsessions?args=vserver:somevip | jq -r '.[] | select(.vserver == "somevip") | .srcip'
jq: error (at <stdin>:0): Cannot index number with string "vserver"

After fixing some minor problems with the full JSON shown in the Q, the invocation:
jq '.[3][].srcip' input.json
yields:
"1.1.1.1"
"3.3.3.3"
Notes
.[3][].scrip is just a shortened form of: .[3] | .[] | .srcip
In your initial query, [.[]] effectively does nothing because the input is an array.

Related

jq - Get objects with latest date

Json looks like this:
cat test.json |jq -r ".nodes[].run_data"
{
"id": "1234",
"status": "PASSED",
"penultimate_status": "PASSED",
"end_time":"2022-02-28T09:50:05Z"
}
{
"id": "4321",
"status": "PASSED",
"penultimate_status": "UNKNOWN",
"end_time": "2020-10-14T13:52:57Z"
}
I want to get "status" and "end_time" of the newest run. Unfortunately the order is not fix. Meaning the newest run can be first in the list, but also last or in the middle...
Use sort_by to bring the items in order, then extract the last item:
jq '
[.nodes[].run_data]
| sort_by(.end_time) | last
| {status, end_time}
' test.json
{
"status": "PASSED",
"end_time": "2022-02-28T09:50:05Z"
}
To get the fields in another format, replace {status, end_time} with your format, e.g. "\(.end_time): Status \(.status)", and set the -r flag as this isn't JSON anymore but raw text.
You can use transpose to map each object with its end_time.
Here I have converted end_time to seconds since Unix epoch and outputted the object with largest seconds value (this is the newest).
[
[. | map(.end_time | strptime("%Y-%m-%dT%H:%M:%SZ") | mktime), [.[0], .[1]]]
| transpose[]
| .[1] += {secs: .[0]} | .[1]
]
| sort_by(.secs) | last
| {status, end_time}
Output
{
"status": "PASSED",
"end_time": "2022-02-28T09:50:05Z"
}
Demo
https://jqplay.org/s/w1z2n2drc7

Extract nested properties from an array of objects

I have the following JSON file :
{
"filter": [
{
"id": "id_1",
"criteria": {
"from": "mail#domain1.com",
"subject": "subject_1"
},
"action": {
"addLabelIds": [
"Label_id_1"
],
"removeLabelIds": [
"INBOX",
"SPAM"
]
}
},
{
"id": "id_2",
"criteria": {
"from": "mail#domain2.com",
"subject": "subject_1"
},
"action": {
"addLabelIds": [
"Label_id_2"
],
"removeLabelIds": [
"INBOX",
"SPAM"
]
}
}
]
}
And I would like to extract emails values : mail#domain1.com and mail#domain2.com
I have tried this command:
jq --raw-output '.filter[] | select(.criteria.from | test("mail"; "i")) | .id'
But does not work, I get this error :
jq: error (at <stdin>:1206): null (null) cannot be matched, as it is
not a string exit status 5
Another point : how to display the value of "id" key, where "from" key value = mail#domain1.com ?
So in my file id = id_1
Do you have an idea ?
If you only need to extract the emails from .criteria.from then this filter is enough as far as I can tell:
jq --raw-output '.filter[].criteria.from' file.json
If some objects don't have a criteria object then you can filter out nulls with:
jq --raw-output '.filter[].criteria.from | select(. != null)' file.json
If you want to keep the emails equal to "mail#domain1.com":
jq --raw-output '.filter[].criteria.from | select(. == "mail#domain1.com")' file.json
If you want to keep the emails that start with "mail#":
jq --raw-output '.filter[].criteria.from | select(. != null) | select(startswith("mail#"))' file.json
I would like to extract emails values
There is a wide spectrum of possible answers, with these
amongst the least specific with respect to where in the JSON the email addresses occur:
.. | objects | .from | select(type=="string")
.. | strings | select(test("#([a-z0-9]+[.])+[a-z]+$"))

Remove slash character in JSON response using jq

Docker Engine API returns container name with / appended
{
"Id": "8dfafdbc3a40",
"Names": [
"/boring_feynman"
],
"Image": "ubuntu:latest",
"ImageID": "d74508fb6632491cea586a1fd7d748dfc5274cd6fdfedee309ecdcbc2bf5cb82",
"Command": "echo 1",
"Created": 1367854155,
"State": "Exited",
"Status": "Exit 0",
"Ports": [{
"PrivatePort": 2222,
"PublicPort": 3333,
"Type": "tcp"
}],
"Labels": {
"com.example.vendor": "Acme",
"com.example.license": "GPL",
"com.example.version": "1.0"
},
"SizeRw": 12288,
"SizeRootFs": 0,
"HostConfig": {
"NetworkMode": "default"
},
"NetworkSettings": {
"Networks": {}
},
"Mounts": [{
"Name": "fac362...80535",
"Source": "/data",
"Destination": "/data",
"Driver": "local",
"Mode": "ro,Z",
"RW": false,
"Propagation": ""
}]
}
I want to remove the slash so the response can be used as a table in JQ:
jq -r '(["Names","Image"] | (., map(length*"-"))), (.[] | [.Names, .Image]) | #tsv'
Currently, when I run the above, I get:
jq: error (at <stdin>:1): array (["/boring_feynman"]) is not valid in a csv row
The problem is not because of / in the .Names field, but in your expression. For filters like #csv or #tsv to work, the values need to be in a scalar format and in an array. But your expression .Name in of type array.
So basically you are passing this result to the #tsv function
[
[
"/boring_feynman"
],
"ubuntu:latest"
]
instead of
[
"/boring_feynman",
"ubuntu:latest"
]
So modifying your filter, you can do below for the JSON in question.
jq -r '(["Names","Image"] | (., map(length*"-"))), ([.Names[], .Image]) | #tsv'
or if you still want to remove the /, use gsub() function
jq -r '(["Names","Image"] | (., map(length*"-"))), ([ (.Names[] | gsub("^/";"")), .Image]) | #tsv'

Jq getting output from nested hash

Hi I am trying to parse below hash with jq
{
"name": "a",
"data": [
{
"sensitive": false,
"type": "string",
"value": "mykeypair"
},
{
"sensitive": false,
"type": "int",
"value": 123
}
]
}
and get output like
a,string,mykeypair
a,int,123
I am able to get output like this
a,string,mykeypair
a,int,mykeypair
a,string,123
a,int,123
jq solution:
jq -r '.name as $n | .data[] | [$n, .type, .value] | #csv' file.json
The output:
"a","string","mykeypair"
"a","int",123
If it's mandatory to output unquoted values:
jq -r '.name as $n | .data[] | [$n, .type, "\(.value)"] | join(",")' file.json
The output:
a,string,mykeypair
a,int,123

jq query with condition and format output/labels

I have a JSON file:
[
{
"platform": "p1",
"id": "5",
"pri": "0",
"sec": "20"
}
]
[
{
"platform": "p2",
"id": "6",
"pri": "10",
"sec": "0"
}
]
I can to format it to the form:
$ jq -c '.[]|{PLATFORM: .platform, ID: .id, PRI: .pri, SEC: .sec}' test.json
{"PLATFORM":"p1","ID":"5","PRI":"0","SEC":"20"}
{"PLATFORM":"p2","ID":"6","PRI":"10","SEC":"0"}
$
but how to ignore SEC/PRI with "0" and get output in form:
PLATFORM:p1, ID:5, SEC:20
PLATFORM:p2, ID:6, PRI:10
I can process it with bash/awk command, but maybe someone have a solution with jq directly.
thank you,
You can use conditional statements to remove the unwanted keys, e.g.:
if (.sec == "0") then del(.sec) else . end
The formatting could be done with #tsv by converting the data to an array, e.g.:
filter.jq
.[] |
if (.sec == "0") then del(.sec) else . end |
if (.pri == "0") then del(.pri) else . end |
to_entries |
map("\(.key | ascii_upcase):\(.value)") |
#tsv
Run it like this:
jq -crf filter.jq test.json
Output:
PLATFORM:p1 ID:5 SEC:20
PLATFORM:p2 ID:6 PRI:10
jq solution:
jq -c 'def del_empty($k): if (.[$k]|tonumber > 0) then . else del(.[$k]) end;
.[] | {PLATFORM: .platform, ID: .id, PRI: .pri, SEC: .sec}
| del_empty("PRI")
| del_empty("SEC")' test.json
The output:
{"PLATFORM":"p1","ID":"5","SEC":"20"}
{"PLATFORM":"p2","ID":"6","PRI":"10"}

Resources