I have been trying to find a way to make sure I can pass the key and values of this json in this link dynamically into influxDB. I have the batch file that is below :
The json file is below from that link :
{
"status": "UP",
"WBAD": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Workbasket Admin"
},
"WBCA": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Workbasket CreateAppWait"
},
"WBDE": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Workbasket default#"
},
"WBEW": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Workbasket eFormWriteFailure"
},
"WBFB": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Workbasket BackgroundProcessing"
},
"WBIC": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Workbasket IncompleteConnections"
},
"WBLB": {
"status": "UP",
"count": "17",
"minDateTime": "23/12/2022 14:50",
"description": "Workbasket LRBackgroundProcess"
},
"AEWB": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Assignment errors for Assign-WorkBasket"
},
"AEWL": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Assignment errors for Assign-Worklist"
},
"FEWB": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Flow errors for Assign-WorkBasket"
},
"FEWL": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Flow errors for Assign-Worklist"
},
"BQBP": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Broken queue System-Queue-BackgroundProcess"
},
"BQDE": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Broken queue System-Queue-DefaultEntry"
},
"CQCA": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Custom query Create App Requests"
},
"JS02": {
"status": "UP",
"description": "Job Scheduler CaseDocumentDeletion (Any one associated node:BackgroundProcessing)"
},
"JS04": {
"status": "UP",
"description": "Job Scheduler PurgeOldSIDExchangeRecords (All associated nodes:BackgroundProcessing)"
},
"JS01": {
"status": "UP",
"description": "Job Scheduler UpdateReferenceData (Any one associated node:BackgroundProcessing)"
}
The batch file :
#!/bin/bash
## GET STATUS
WBLB_STATUS=`curl -s http://example:8080/Cluster | jq -r '.WBLB.status'`
WBCA_STATUS=`curl -s http://example:8080/Cluster | jq -r '.WBCA.status'`
if [ "$WBLB_STATUS" = "UP" ]; then
echo "app_custom,wblb_status="UP" wlb_status_code=1"
elif [ "$WBLB_STATUS" = "DOWN" ]; then
echo "app_custom,wblb_status="DOWN" wblb_status_code=0"
fi
exit
The output is
app_custom,wblb_status=UP wlb_status_code=1
I do not want to each key with if but would like to have the output like this below
app_custom,app_wblb_status=UP wlb_status_code=1
app_custom,app_wblc_status=UP wlb_status_code=1
app_custom,app_wbad_status=UP wlb_status_code=1
......
I would want to use this to pass to the influx DB using this conf :
[[inputs.exec]]
commands = ["/etc/telegraf/telegraf.d/app_test.sh"]
data_format = "influx"
timeout = "30s"
interval = "2m"
Use the to_entries function to transform your entries into a list of dictionaries with key and value members, and then you have a data structure that is much easier to filter.
That is, running jq to_entries data.json (where data.json contains your sample data) produces output like:
[
{
"key": "status",
"value": "UP"
},
{
"key": "WBAD",
"value": {
"status": "UP",
"count": "0",
"minDateTime": "",
"description": "Workbasket Admin"
}
},
...
We can extract the keys and values we want from that, and then use the #tsv filter to generate output that's easier to work with in the shell. The following jq command line:
jq -r 'to_entries[]|select(.key != "status")|[.key, .value.status]|#tsv' data.json
Produces as output:
WBAD UP
WBCA UP
WBDE UP
WBEW UP
WBFB UP
WBIC UP
WBLB UP
AEWB UP
AEWL UP
FEWB UP
FEWL UP
BQBP UP
BQDE UP
CQCA UP
JS02 UP
JS04 UP
JS01 UP
We can read values using the read shell function:
#!/bin/bash
jq -r 'to_entries[]|select(.key != "status")|[.key, .value.status]|#tsv' data.json |
while read key status; do
[[ $status = "UP" ]] && code=1 || code=0
echo "app_custom,${key,,}_status=\"$status\" wlb_status_code=$code"
done
Which produces:
app_custom,wbad_status="UP" wlb_status_code=1
app_custom,wbca_status="UP" wlb_status_code=1
app_custom,wbde_status="UP" wlb_status_code=1
app_custom,wbew_status="UP" wlb_status_code=1
app_custom,wbfb_status="UP" wlb_status_code=1
app_custom,wbic_status="UP" wlb_status_code=1
app_custom,wblb_status="UP" wlb_status_code=1
app_custom,aewb_status="UP" wlb_status_code=1
app_custom,aewl_status="UP" wlb_status_code=1
app_custom,fewb_status="UP" wlb_status_code=1
app_custom,fewl_status="UP" wlb_status_code=1
app_custom,bqbp_status="UP" wlb_status_code=1
app_custom,bqde_status="UP" wlb_status_code=1
app_custom,cqca_status="UP" wlb_status_code=1
app_custom,js02_status="UP" wlb_status_code=1
app_custom,js04_status="UP" wlb_status_code=1
app_custom,js01_status="UP" wlb_status_code=1
You can use to_entries to split up the items into an array of key-value pairs, then string interpolation to piece together the output strings:
curl -s http://example:8080/Cluster | jq -r '
to_entries[] | select(.value | type == "object")
| [.key, .value.status] as [$id, $status]
| "app_custom,\($id | ascii_downcase)_status=\($status) wlb_status_code=\(["DOWN","UP"] | index($status))"
'
app_custom,wbad_status=UP wlb_status_code=1
app_custom,wbca_status=UP wlb_status_code=1
app_custom,wbde_status=UP wlb_status_code=1
app_custom,wbew_status=UP wlb_status_code=1
app_custom,wbfb_status=UP wlb_status_code=1
app_custom,wbic_status=UP wlb_status_code=1
app_custom,wblb_status=UP wlb_status_code=1
app_custom,aewb_status=UP wlb_status_code=1
app_custom,aewl_status=UP wlb_status_code=1
app_custom,fewb_status=UP wlb_status_code=1
app_custom,fewl_status=UP wlb_status_code=1
app_custom,bqbp_status=UP wlb_status_code=1
app_custom,bqde_status=UP wlb_status_code=1
app_custom,cqca_status=UP wlb_status_code=1
app_custom,js02_status=UP wlb_status_code=1
app_custom,js04_status=UP wlb_status_code=1
app_custom,js01_status=UP wlb_status_code=1
Demo
Related
My original JSON is given below.
[
{
"id": "1",
"name": "AA_1",
"total": "100002",
"files": [
{
"filename": "8665b987ab48511eda9e458046fbc42e.csv",
"filename_original": "some.csv",
"status": "3",
"total": "100002",
"time": "2020-08-24 23:25:49"
}
],
"status": "3",
"created": "2020-08-24 23:25:49",
"filenames": "8665b987ab48511eda9e458046fbc42e.csv",
"is_append": "0",
"is_deleted": "0",
"comment": null
},
{
"id": "4",
"name": "AA_2",
"total": "43806503",
"files": [
{
"filename": "1b4812fe634938928953dd40db1f70b2.csv",
"filename_original": "other.csv",
"status": "3",
"total": "21903252",
"time": "2020-08-24 23:33:43"
},
{
"filename": "63ab85fef2412ce80ae8bd018497d8bf.csv",
"filename_original": "some.csv",
"status": "2",
"total": 0,
"time": "2020-08-24 23:29:30"
}
],
"status": "2",
"created": "2020-08-24 23:35:51",
"filenames": "1b4812fe634938928953dd40db1f70b2.csv&&63ab85fef2412ce80ae8bd018497d8bf.csv",
"is_append": "0",
"is_deleted": "0",
"comment": null
}
]
From this JSON I want to create new objects by combining fields from objects which have status: 2 and their files which also have the same pair, status: 2.
So, I am expecting a JSON array as below.
[
{
"id": "4",
"name": "AA_2",
"file_filename": "63ab85fef2412ce80ae8bd018497d8bf.csv",
"file_status": 2
}
]
So far I tried with this JQ filter:
.[]|select(.status=="2")|[{id:.id,file_filename:.files[].filename,file_status:.files[].status}]
But this produces some invalid data.
[
{
"id": "4", # want to remove this as file.status != 2
"file_filename": "1b4812fe634938928953dd40db1f70b2.csv",
"file_status": "3"
},
{
"id": "4",
"file_filename": "1b4812fe634938928953dd40db1f70b2.csv",
"file_status": "2"
},
{
"id": "4", # Repeat
"file_filename": "63ab85fef2412ce80ae8bd018497d8bf.csv",
"file_status": "3"
},
{
"id": "4", # Repeat
"file_filename": "63ab85fef2412ce80ae8bd018497d8bf.csv",
"file_status": "2"
}
]
How do I filter the new JSON using JQ and remove these duplicate objects?
By applying [] operator to files twice, you're running into a combinatorial explosion. That needs to be avoided, for example:
[ .[] | select(.status == "2") | {id, name} + (.files[] | select(.status == "2") | {file_filename: .filename, file_status: .status}) ]
Online demo
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
I am trying to transform the map of the object in json to List using JQ ...
Source:
{
"title": "title",
"keyword": "keyword",
"desc": {
"user1": {
"name": "kumar",
"Duration": null,
"Time": null,
" Dominance": "Upper Field First"
},
"user2": {
"id": "user2",
"name": "user2",
"Duration": null,
"Time": null,
" Dominance": "Upper Field First"
}
}
}
Target:
[
{
"id": "user1",
"name": "kumar",
"Duration": null,
"Time": null,
"Dominance": "Upper Field First"
},
{
"id": "user2",
"name": "user2",
"Duration": null,
"Time": null,
"Dominance": "Upper Field First"
}
]
I tried various options like , but not able to get the extact thing i need.
.desc | . as $in| keys[]
to_entries
JQ Workspace ::: https://jqplay.org/s/MiJ9w1Sz5L
The following filter will do what you want, assuming you've fixed the input:
.desc
| to_entries
| map( {id: .key} + .value)
To understand this, simply read up on to_entries in the online manual (see jq).
I have a deep json. Sometimes, I need to look for the json path for a key containing certain word.
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"creationTimestamp": "2019-03-28T21:09:42Z",
"labels": {
"bu": "finance",
"env": "prod"
},
"name": "auth",
"namespace": "default",
"resourceVersion": "2786",
"selfLink": "/api/v1/namespaces/default/pods/auth",
"uid": "ce73565a-519d-11e9-bcb7-0242ac110009"
},
"spec": {
"containers": [
{
"command": [
"sleep",
"4800"
],
"image": "busybox",
"imagePullPolicy": "Always",
"name": "busybox",
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File",
"volumeMounts": [
{
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
"name": "default-token-dbpcm",
"readOnly": true
}
]
}
],
"dnsPolicy": "ClusterFirst",
"nodeName": "node01",
"priority": 0,
"restartPolicy": "Always",
"schedulerName": "default-scheduler",
"securityContext": {},
"serviceAccount": "default",
"serviceAccountName": "default",
"terminationGracePeriodSeconds": 30,
"tolerations": [
{
"effect": "NoExecute",
"key": "node.kubernetes.io/not-ready",
"operator": "Exists",
"tolerationSeconds": 300
},
{
"effect": "NoExecute",
"key": "node.kubernetes.io/unreachable",
"operator": "Exists",
"tolerationSeconds": 300
}
],
"volumes": [
{
"name": "default-token-dbpcm",
"secret": {
"defaultMode": 420,
"secretName": "default-token-dbpcm"
}
}
]
},
"status": {
"conditions": [
{
"lastProbeTime": null,
"lastTransitionTime": "2019-03-28T21:09:42Z",
"status": "True",
"type": "Initialized"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2019-03-28T21:09:50Z",
"status": "True",
"type": "Ready"
},
{
"lastProbeTime": null,
"lastTransitionTime": null,
"status": "True",
"type": "ContainersReady"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2019-03-28T21:09:42Z",
"status": "True",
"type": "PodScheduled"
}
],
"containerStatuses": [
{
"containerID": "docker://b5be8275555ad70939401d658bb4e504b52215b70618ad43c2d0d02c35e1ae27",
"image": "busybox:latest",
"imageID": "docker-pullable://busybox#sha256:061ca9704a714ee3e8b80523ec720c64f6209ad3f97c0ff7cb9ec7d19f15149f",
"lastState": {},
"name": "busybox",
"ready": true,
"restartCount": 0,
"state": {
"running": {
"startedAt": "2019-03-28T21:09:49Z"
}
}
}
],
"hostIP": "172.17.0.37",
"phase": "Running",
"podIP": "10.32.0.4",
"qosClass": "BestEffort",
"startTime": "2019-03-28T21:09:42Z"
}
}
Currently If i need the podIP, then I do that this way to find the object which has the search keyword and then I build the path
curl myson | jq "[paths]" | grep "IP" --context=10
Is there any nice shortcut to simplify this? What I really need is - all the paths which could have the matching key.
spec.podIP
spec.hostIP
select paths containing keyword in their last element, and use join(".") to generate your desired output.
paths
| select(.[-1] | type == "string" and contains("keyword"))
| join(".")
.[-1] returns the last element of an array,
type == "string" is required because an array index is a number and numbers and strings can't be checked for their containment.
You may want to specify -r option.
As #JeffMercado implicitly suggested you can set the query from command line without touching the script:
jq -r 'paths
| select(.[-1] | type == "string" and contains($q))
| join(".")' file.json --arg q 'keyword'
You can stream the input in, which provides paths and values. You could then inspect the paths and optionally output the values.
$ jq --stream --arg pattern 'IP' '
select(length == 2 and any(.[0][] | strings; test($pattern)))
| "\(.[0] | join(".")): \(.[1])"
' input.json
"status.hostIP: 172.17.0.37"
"status.podIP: 10.32.0.4"
shameless plug
https://github.com/TomConlin/json_to_paths
because sometime you do not even know the component you want to filter for before you see what is there.
json2jqpath.jq file.json
.
.apiVersion
.kind
.metadata
.metadata|.creationTimestamp
.metadata|.labels
.metadata|.labels|.bu
.metadata|.labels|.env
.metadata|.name
.metadata|.namespace
.metadata|.resourceVersion
.metadata|.selfLink
.metadata|.uid
.spec
.spec|.containers
.spec|.containers|.[]
.spec|.containers|.[]|.command
.spec|.containers|.[]|.command|.[]
.spec|.containers|.[]|.image
.spec|.containers|.[]|.imagePullPolicy
.spec|.containers|.[]|.name
.spec|.containers|.[]|.resources
.spec|.containers|.[]|.terminationMessagePath
.spec|.containers|.[]|.terminationMessagePolicy
.spec|.containers|.[]|.volumeMounts
.spec|.containers|.[]|.volumeMounts|.[]
.spec|.containers|.[]|.volumeMounts|.[]|.mountPath
.spec|.containers|.[]|.volumeMounts|.[]|.name
.spec|.containers|.[]|.volumeMounts|.[]|.readOnly
.spec|.dnsPolicy
.spec|.nodeName
.spec|.priority
.spec|.restartPolicy
.spec|.schedulerName
.spec|.securityContext
.spec|.serviceAccount
.spec|.serviceAccountName
.spec|.terminationGracePeriodSeconds
.spec|.tolerations
.spec|.tolerations|.[]
.spec|.tolerations|.[]|.effect
.spec|.tolerations|.[]|.key
.spec|.tolerations|.[]|.operator
.spec|.tolerations|.[]|.tolerationSeconds
.spec|.volumes
.spec|.volumes|.[]
.spec|.volumes|.[]|.name
.spec|.volumes|.[]|.secret
.spec|.volumes|.[]|.secret|.defaultMode
.spec|.volumes|.[]|.secret|.secretName
.status
.status|.conditions
.status|.conditions|.[]
.status|.conditions|.[]|.lastProbeTime
.status|.conditions|.[]|.lastTransitionTime
.status|.conditions|.[]|.status
.status|.conditions|.[]|.type
.status|.containerStatuses
.status|.containerStatuses|.[]
.status|.containerStatuses|.[]|.containerID
.status|.containerStatuses|.[]|.image
.status|.containerStatuses|.[]|.imageID
.status|.containerStatuses|.[]|.lastState
.status|.containerStatuses|.[]|.name
.status|.containerStatuses|.[]|.ready
.status|.containerStatuses|.[]|.restartCount
.status|.containerStatuses|.[]|.state
.status|.containerStatuses|.[]|.state|.running
.status|.containerStatuses|.[]|.state|.running|.startedAt
.status|.hostIP
.status|.phase
.status|.podIP
.status|.qosClass
.status|.startTime
I ran curl command and then parsed the value ("id").
request:
curl "http://192.168.22.22/test/index/limit:1/page:1/sort:id/pag1.json" | jq -r '.[0].id'
curl response:
[
{
"id": "381",
"org_id": "9",
"date": "2018-10-10",
"info": "THIS IS TEST",
"uuid": "5bbd1b41bc",
"published": 1,
"an": "2",
"attribute_count": "4",
"orgc_id": "8",
"timestamp": "1",
"dEST": "0",
"sharing": "0",
"proposal": false,
"locked": false,
"level_id": "1",
"publish_timestamp": "0",
"disable_correlation": false,
"extends_uuid": "",
"Org": {
"id": "5",
"name": "test",
"uuid": "5b9bc"
},
"Orgc": {
"id": "1",
"name": "test",
"uuid": "5b9f93bdeac1b41bc"
},
"ETag": []
}
]
jq response:
381
Now I'm trying to get the "id" number 381, and then to create a new JSON file on the disk when I place the "id" number in the right place.
The new JSON file for example:
{
"request": {
"Event": {
"id": "381",
"task": "new"
}
}
}
Given your input, this works:
jq -r '{"request": {"Event": {"id": .[0].id, "task": "new"}}}' > file