Issue with json extraction key value - json

I have this jq to work with another json file somehow is not picking this up based on key and value. I would like to get the status of each value either UP or DOWN for each key. The code is below:
curl -s http://example:8080/external_indicator | jq -r '
to_entries[] | select(.value | type == "object")
| [.key, .value.components.status] as [$id, $status]
| "app_custom,\($id=\($status) wlb_status_code=\(["DOWN","UP"] | index($status))"
'
Desired output should be:
app_custom,db=UP status_code=1
app_custom,angleDS=UP status_code=1
app_custom,argosleDS=UP status_code=1
But current output is :
app_custom,components_status=null status_code=null
Json file is
{
"status": "UP",
"components": {
"db": {
"status": "UP",
"components": {
"DS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 194
}
},
"angusDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 166
}
},
"argyleDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 155
}
},
"ayrDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 166
}
},
"banffDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 156
}
},
"caithnessDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 156
}
},
"clackmannanDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 155
}
},
"DS": {
"status": "UP",
"details": {
"database": "H2",
"validationQuery": "isValid()"
}
},
"dumbartonDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 155
}
},
"eastLothianDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 168
}
},
"fifeDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 166
}
},
"glasgowDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 171
}
},
"invernessDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 166
}
},
"kirkcudbrightDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 166
}
},
"lanarkDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 159
}
},
"midLothianDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 157
}
},
"morayDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 156
}
},
"orkneyDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 156
}
},
"perthDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 169
}
},
"renfrewDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 167
}
},
"adesDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 156
}
},
"stirlingDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 157
}
},
"sutherlandDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 156
}
},
"westLothianDS": {
"status": "UP",
"details": {
"database": "Informix Dynamic Server",
"validationQuery": "select count(1) from systables",
"result": 155
}
}
}
},
"discoveryComposite": {
"description": "Discovery Client not initialized",
"status": "UNKNOWN",
"components": {
"discoveryClient": {
"description": "Discovery Client not initialized",
"status": "UNKNOWN"
}
}
},
"diskSpace": {
"status": "UP",
"details": {
"total": 128300593152,
"free": 37138010112,
"threshold": 10485760,
"exists": true
}
},
"livenessState": {
"status": "UP"
},
"ping": {
"status": "UP"
},
"rabbit": {
"status": "UP",
"details": {
"version": "3.7.28"
}
},
"readinessState": {
"status": "UP"
},
"refreshScope": {
"status": "UP"
}
},
"groups": [
"liveness",
"readiness"
]
}
How would I be able to extract the key and get it based on this output
app_custom,db=UP status_code=1
app_custom,angleDS=UP status_code=1
app_custom,argosleDS=UP status_code=1

Your filter does not match up with the structure of your input. Your input has a recursive structure and your filter is only looking at the top level. The status is on the children of each component object so .value.components.status is incorrect.
I'm not sure what exactly your goal is but since this is recursive, you could use .. to descend through the tree and filter objects that have a components property and pick values to display.
$ curl -s ... | jq -r '
.. | .components? // empty | to_entries[]
| [.key, .value.status] as [$id, $status]
| "app_custom,\($id)=\($status) status_code=\(if $status=="UP" then 1 else 0 end)"
'
app_custom,db=UP status_code=1
app_custom,discoveryComposite=UNKNOWN status_code=0
app_custom,diskSpace=UP status_code=1
app_custom,livenessState=UP status_code=1
app_custom,ping=UP status_code=1
app_custom,rabbit=UP status_code=1
app_custom,readinessState=UP status_code=1
app_custom,refreshScope=UP status_code=1
app_custom,DS=UP status_code=1
app_custom,angusDS=UP status_code=1
app_custom,argyleDS=UP status_code=1
app_custom,ayrDS=UP status_code=1
app_custom,banffDS=UP status_code=1
app_custom,caithnessDS=UP status_code=1
app_custom,clackmannanDS=UP status_code=1
app_custom,dumbartonDS=UP status_code=1
app_custom,eastLothianDS=UP status_code=1
app_custom,fifeDS=UP status_code=1
app_custom,glasgowDS=UP status_code=1
app_custom,invernessDS=UP status_code=1
app_custom,kirkcudbrightDS=UP status_code=1
app_custom,lanarkDS=UP status_code=1
app_custom,midLothianDS=UP status_code=1
app_custom,morayDS=UP status_code=1
app_custom,orkneyDS=UP status_code=1
app_custom,perthDS=UP status_code=1
app_custom,renfrewDS=UP status_code=1
app_custom,adesDS=UP status_code=1
app_custom,stirlingDS=UP status_code=1
app_custom,sutherlandDS=UP status_code=1
app_custom,westLothianDS=UP status_code=1
app_custom,discoveryClient=UNKNOWN status_code=0
Here it is written a bit differently to hopefully illustrate what part is doing what.
.. # recurse through the object tree
| .components? // empty # get the components object or skip if none
| to_entries[] # convert the object to entries
| [.key, .value.status] as [$id, $status] # bind $id and $status variables
| ($id | gsub(" +"; "_")) as $fixedId # replace spaces in id with underscores
| (if $status=="UP" then 1 else 0 end) as $statusCode # set statusCode to 1 if $status is "UP"
| "app_custom,\($fixedId)=\($status) status_code=\($statusCode)" # construct the final string given the components above

Related

JQ Error: Cannot iterate over string while trying to map IP and Ports

I have a below json output, I would love to remove duplicate data and map the data in a table format using jq. I am using the below query but I keep getting an error;
Cannot iterate over string ("78.45.196...)
e.t.c.
Json data
[
{
"ip": "78.45.196.23",
"timestamp": "1616566245",
"ports": [
{
"port": 5060,
"proto": "tcp",
"status": "open",
"reason": "syn-ack",
"ttl": 50
}
]
},
{
"ip": "67.89.378.82",
"timestamp": "1616566255",
"ports": [
{
"port": 2000,
"proto": "tcp",
"status": "open",
"reason": "syn-ack",
"ttl": 50
}
]
},
{
"ip": "67.89.378.82",
"timestamp": "1616566255",
"ports": [
{
"port": 2080,
"proto": "tcp",
"status": "open",
"reason": "syn-ack",
"ttl": 50
}
]
},
{
"ip": "78.45.196.23",
"timestamp": "1616566245",
"ports": [
{
"port": 5060,
"proto": "tcp",
"status": "open",
"reason": "syn-ack",
"ttl": 50
}
]
},
{
"ip": "67.89.378.82",
"timestamp": "1616566255",
"ports": [
{
"port": 2000,
"proto": "tcp",
"status": "open",
"reason": "syn-ack",
"ttl": 50
}
]
},
{
"ip": "78.45.196.23",
"timestamp": "1616566245",
"ports": [
{
"port": 5080,
"proto": "tcp",
"status": "open",
"reason": "syn-ack",
"ttl": 50
}
]
}
]
My query
jq -r '.[][] | group_by(.ip) | map({ip: .ip, ports: map(.ports[].port) | add | unique})' jsonfile.json
Expected output
To remove duplicates and get ip and ports.
Or can one explain to me how to get unique values from both IP and ports.
[
{"ip:" "67.89.378.82", "ports:"[2000, 2080]},
{"ip:" "78.45.196.23", "ports:"[5060, 5080]}
]
Construct your desired JSON immediately following the group_by()
group_by(.ip) |
map
(
{
ip: .[0].ip,
ports: [ .[].ports[].port ] | unique
}
)
jq play link
Follow-up question to discard IPs that have only port as 0
group_by(.ip) |
map
(
{
ip: .[0].ip,
ports: [ .[].ports[] | select(.port != 0 ).port ] | unique
} |
select(.ports | length > 0)
)

Looping and searching through JSON using PowerShell

I have a JSON file that has following contents:
{
"status": "UP",
"details": {
"graphDBCheck": {
"status": "UP"
},
"ds": {
"status": "UP",
"details": {
"total": 100,
"free": 50,
"threshold": 30
}
},
"db": {
"status": "UP",
"details": {
"ADS": {
"status": "UP",
"details": {
"database": "Influx",
"hello": "Hello"
}
},
"EARDS": {
"status": "UP",
"details": {
"database": "Oracle",
"hello": "Hello"
}
},
"EFRDS": {
"status": "UP",
"details": {
"database": "Sybase",
"hello": "Hello"
}
}
}
}
}
}
I need to be able to transform this into a CSV file that has each element's name as header and it's status or value as the next row. First "status" would have column name "API_Status"
For instance:
API_Status,graphDBCheck,ds,db,ADS,EARDS,EFRDS
UP,UP,UP,UP,UP,UP,UP
Challenge here is to make this dynamic so the output will always include any other element added that has "status" in it.
I tried this and it works but I need a dynamic way do to this:
$x = Invoke-RestMethod $url -Verbose:$VerbosePreference
[pscustomobject][ordered]#{
'API_Status' = $x.status
'db' = $x.details.db.status
'ds' = $x.details.diskspace.status
'ds_Total' = $x.details.ds.details.total
'ds_Free' = $x.details.ds.details.free
'graphDBCheck' = $x.details.graphDBCheck.status
'ADS' = $x.details.db.details.auroraDataSource.status
'EARDS' = $x.details.db.details.EARDS.status
'EFRDS' = $x.details.db.details.edsFirstRowsDataSource.status
}
In an ideal world, the json would be structured like this, as an expandable array with uniform properties.
[
{
"name": "API_Status",
"status": "UP"
},
{
"name": "graphDBCheck",
"status": "UP"
},
{
"name": "ds",
"status": "UP"
},
{
"name": "db",
"status": "UP"
},
{
"name": "ADS",
"status": "UP"
},
{
"name": "EARDS",
"status": "UP"
},
{
"name": "EFRDS",
"status": "UP"
}
]
Or as a csv:
name,status
API_Status,UP
graphDBCheck,UP
ds,UP
db,UP
ADS,UP
EARDS,UP
EFRDS,UP
There's plenty of other posts about looping through powershell properties Iterate over PSObject properties in PowerShell or looping through json properties: Iterating through a JSON file PowerShell

Key value to be added in nested array

This is my json which i am trying to parse using jq
{
"orgs": {
"org1": [{
"space": "landscape2",
"tag": "landscape2",
"manager": {
"destination": "destination1"
}},
{
"space": "landscape3",
"tag": "landscape3",
"manager": {
"destination1": "approuter",
"destination2": "approuter2"
}},
{
"space": "landscape4",
"app": "",
"l_port_increment": 25,
"host": "",
"port": ""
}],
"org2": [
{
"space": "landscape1",
"app": "ain-hana-chisel-cs",
"l_port_increment": 13,
"host": "10.03.76.234",
"port": "30044"
},
{
"space": "landscape3",
"tag": "landscape3",
"manager1": {
"destination5": "service-v2",
"destination6": "service-v2"
},
"manager": {
"destination": "destination1"
},
"l_port_increment": 25,
"host": "",
"port": ""
} ] } }
I am looking for an output as below where tag should be one of the filter.
{
"orgs: "org1",
"space": "landscape3",
"tag": "landscape3",
"manager": {
"destination1": "approuter",
"destination2": "approuter2"
}
}
{
"orgs": "org2",
"space": "landscape3",
"tag": "landscape3",
"manager1": {
"destination5": "service-v2",
"destination6": "service-v2"
},
"manager": {
"destination": "destination1"
},
"l_port_increment": 25,
"host": "",
"port": ""
}
Using this code, I can achieve the result partially, however unable to get the orgs details.
.orgs[] | .[ ] | select(."tag"=="landscape3") | select (."manager")
My actual output is as below. How to do it by using jq? I have tried several ways but unable tot get the desired output
{
"space": "landscape3",
"tag": "landscape3",
"manager": {
"destination1": "approuter",
"destination2": "approuter2"
}
}
{
"space": "landscape3",
"tag": "landscape3",
"manager1": {
"destination5": "service-v2",
"destination6": "service-v2"
},
"manager": {
"destination": "destination1"
},
"l_port_increment": 25,
"host": "",
"port": ""
}
Your description of the task is not much clear, but I guess you're looking for something like this:
.orgs
| keys_unsorted[] as $k
| {orgs:$k} + first(.[$k][] | select(has("manager") and .tag == "landscape3"))
For each key in orgs, selects the objects which have manager as key and tag: landscape key-value pair from corresponding array, adds orgs: <key> to the first and outputs the resulting object. If multiple objects are selected, the rest except the first one is omitted.

Parse and filter complex JSON Response in Python (the easy compute method)

I have a list of dictionaries (basically JSON Response of an endpoint)
I would need to Parse this 16000 lines of json objects and fitler the documents/objects which match criteria that
whose leaf element/field : statusInfo/status in not "UP" and of those filtered objects, just return "name" , "serviceUrl","status"
example :
"ADMIN-V1" "http://aws-ec2.aws.com:4435" "Warning"
I have been researching about JSONPath module , but there is no good documentation about it, and I could not find any easier way.
Any guidance is highly appreciated.
here is a snippet from long 16000 lines of JSON response.
[
{
"id": "9c108ec5",
"name": "USER-V2",
"managementUrl": "http://aws-ec2.aws.com:5784/",
"healthUrl": "http://aws-ec2.aws.com:5784/health",
"serviceUrl": "http://aws-ec2.aws.com:5784/",
"statusInfo": {
"status": "UP",
"timestamp": 1566663146681,
"details": {
"description": " Eureka Discovery Client",
"status": "UP"
}
},
"source": "discovery",
"metadata": {},
"info": {
"component": "user",
"description": "User REST Resource",
"version": "2.2.1",
"git": {
"commit": {
"time": "07/27/2018 # 15:06:55 CDT",
"id": "b2a1b37"
},
"branch": "refs/tags/v2.2.1"
}
}
},
{
"id": "1a381f20",
"name": "ADMIN-V1",
"managementUrl": "http://aws-ec2.aws.com:4435/",
"healthUrl": "http://aws-ec2.aws.com:4435/health",
"serviceUrl": "http://aws-ec2.aws.com:4435/",
"statusInfo": {
"status": "Warning",
"timestamp": 1566663146682,
"details": {
"description": "Spring Cloud Eureka Discovery Client",
"status": "Warning"
}
},
"source": "discovery",
"metadata": {},
"info": {
"description": "Exchange Admin REST Resource",
"api": {
"version": "1.2.1",
"name": "admin",
"link": "https://app.swaggerhub.com/apis/AWSExchange/admin/1.2.1"
},
"implementation": "admin",
"version": "1.1.0",
"git": {
"commit": {
"time": "01/04/2019 # 15:36:48 UTC",
"id": "39d5551"
},
"branch": "refs/tags/v1.1.0"
}
}
}
]
If your json file contains one big array, you'll want to stream that file in truncating out the array. Then use fromstream/1 to rebuild the objects and filtering them out as you go.
I don't have a representative file to test out the performance myself, but give this a try:
$ jq --stream -n 'fromstream(1|truncate_stream(inputs))
| select(.statusInfo.status != "UP")
| .name, .serviceUrl, .statusInfo.status
' input.json

Convert json file to R object in R

I am trying to convert a json file in R. The format of the data is as follows:
{
"id": "xyz",
"root": {
"author": {
"name": "xyz",
"email": "xyx#xyz.org",
"date": "2014-10-08T00:10:30Z"
},
"authorer": {
"name": "xyz",
"email": "xyx#xyz.org",
"date": "2014-10-08T00:11:30Z"
},
"message": "This a test json",
"root": {
"id": "xyz1",
"url": "xyz"
},
"url": "xyz",
"message_count": 0
},
"url": "xyz",
"html_url": "xyz",
"comments_url": "abc",
"author": null,
"authorer": null,
"parent": [
{
"id": "xyz3",
"url": "xyz",
"html_url": "xyz"
}
]
}
After this a similar row begins, with {having the same formatted text }This is the code I wrote in R
install.packages("rjson")
library(rjson)
df <- fromJSON(paste(readLines("file.json"), collapse=""))
View(df)
I was wondering how do make this file readable in R? I wanted to see them as columns like this:
id root/author/name root/author/email root/author/date root/authorer/name
Refer to here: http://konklone.io/json/?id=dfeae96a607c7541b8fe (of how the input and output should look like).
I have provided a new link here for two rows: http://konklone.io/json/?id=3b01a02e17ec4fde3357
Thanks a lot
Is this what you want:
json <- '{
"id": "xyz",
"root": {
"author": {
"name": "xyz",
"email": "xyx#xyz.org",
"date": "2014-10-08T00:10:30Z"
},
"authorer": {
"name": "xyz",
"email": "xyx#xyz.org",
"date": "2014-10-08T00:11:30Z"
},
"message": "This a test json",
"root": {
"id": "xyz1",
"url": "xyz"
},
"url": "xyz",
"message_count": 0
},
"url": "xyz",
"html_url": "xyz",
"comments_url": "abc",
"author": null,
"authorer": null,
"parent": [
{
"id": "xyz3",
"url": "xyz",
"html_url": "xyz"
}
]
}'
out <- jsonlite::fromJSON(json)
out[vapply(out, is.null, logical(1))] <- "none"
data.frame(out, stringsAsFactors = FALSE)[,1:5]
id root.author.name root.author.email root.author.date root.authorer.name
1 xyz xyz xyx#xyz.org 2014-10-08T00:10:30Z xyz