jq parsing json input with variables - json

I have this input:
{
"users": [
{
"name": "tester-01",
"user": {
"username": "tester01"
}
},
{
"name": "tester-02",
"user": {
"username": "tester02"
}
}
],
"current-user": "tester-02"
}
Using jq (1.5), I want to print the username that matches current-user.
Can anyone share how this would be done or tips to get me started?

This was my solution.
cat 99 | jq -r '."current-user" as $foo | .users[] | select(.name == $foo).user'
{
"username": "tester02"
}

The select solution is good. Here is an alternative that uses foreach.
foreach .users[] as $u (
."current-user"
; .
; if . == $u.name then $u.user.username else empty end
)

Related

iterate on key to get the contents of the key

IF I have json that looks like
{
"items": [
{
"name": "issue1",
"spec": {
"config": {
"setting1": abc,
"setting2": {
"name": "xyz"
}
},
"files": {
"name": "cde",
"path": "/home"
},
"program": {
"name": "apache"
}
}
}
]
}
and I want to have iteration at .items[0].spec where the key config,files,program's contents can be shown.. something like
config:
{
"setting1": abc,
"setting2": {
"name": "xyz"
}
}
files:
{
"name": "cde",
"path": "/home"
}
program:
{
"name": "apache"
}
and there might be things more or less than config/files/programs for each items.
I know that I can get the list of keys by jq -r '.items[0].spec| to_entries[].key' but not sure about formating the output and getting the contents of .items[].spec.xxxxx like above.
I also got very close by jq -r '{test: .items[0].spec | with_entries(select(.value != null)) }' but I want to seperate each item per key
Also this got me even closer! but how do you get the json syntax of the object to display uncompressed?
jq -r '.items[].spec | keys[] as $k | "\($k):\n \(.[$k])"'
The "," operator is the magic ingredient you seem to be looking for:
.items[].spec | keys[] as $k | $k, .[$k]

Trying to merge 2 JSON documents using JQ

I'm using JQ CLI to merge JSON from document to another. The issue I am facing is that I have select by the value of a property, rather than by a numeric array index
The first file contains a chunk of JSON jqtest.json:
{
"event": [
{
"listen": "test",
"script": {
"exec": [],
"type": "text/javascript"
}
}
]
}
The second file is where I want to merge the JSON into under "accounts" collection.json:
{
"item": [
{
"name": "accounts",
"item": [
{
"name": "Retrieves the collection of Account resources."
}
]
},
{
"name": "accounts mapped",
"item": [
{
"name": "Retrieves the collection of AccountMapped resources."
}
]
}
]
}
What i am trying to do is merge it under "accounts" and under "name": "Retrieves the collection of Account resources." I use the command:
jq -s '
.[0].event += .[1].item |
map(select(.name=="accounts")) |
.[].item
' jqtest.json collection.json
But when executed nothing is outputted. What am doing wrong with JQ or is there another tool i can use to accomplish this?
{
"item": [
{
"name": "accounts",
"item": [
{
"name": "Retrieves the collection of Account resources.",
"event": [
{
"listen": "test",
"script": {
"exec": [],
"type": "text/javascript"
}
}
]
},
{
"name": "accounts mapped",
"item": [
{
"name": "Retrieves the collection of AccountMapped resources."
}
]
}
]
}
]
}
To merge two objects, one can use obj1 + obj2. From this, it follows that obj1 += obj2 can be used to merge an object (obj2) into another existing object (obj1).
Maybe that's what you trying to use. If so, you were missing parens around the expression producing the object to merge into (causing the code to be misparsed), you have the operands to += backwards, you don't actually produce the correct objects on each side of += (or even objects at all), and you didn't narrow down your output (accidentally including jqtest in the output).
Fixed:
jq -s '
( .[1].item[] | select( .name == "accounts" ) | .item[] ) += .[0] | .[1]
' jqtest.json collection.json
Demo on jqplay
I find the following clearer (less mental overhead):
jq -s '
.[0] as $to_insert |
.[1] | ( .item[] | select( .name == "accounts" ) | .item[] ) += $to_insert
' jqtest.json collection.json
Demo
That said, I would avoid slurping in favour of --argfile.
jq --argfile to_insert jqtest.json '
( .item[] | select( .name == "accounts" ) | .item[] ) += $to_insert
' collection.json
Demo on jqplay

Using jq to fetch key-value pairs from a json file

I am trying to get key#value pairs of JSON file below using jq
{
"STUFF_RELATED1": "STUFF_RELATED1",
"STUFF_RELATED2": "STUFF_RELATED2",
"THINGS": {
"THING_2": {
"details": {
"stuff_branch": "user/dev"
},
"repository": "path/to/repo",
"branch": "master",
"revision": "dsfkes4s34jlis4jsj4lis4sli3"
},
"THING_1": {
"details": {
"stuff_branch": "master"
},
"repository": "path/to/repo",
"branch": "master",
"revision": "dsfkes4s34jlis4jsj4lis4sli3"
}
},
"STUFF": {
"revision": "4u324i324iy32g",
"branch": "master"
}
}
The key#value pair should look like this:
THING_1#dsfkes4s34jlis4jsj4lis4sli3
Currently I have tried this on my own:
jq -r ' .THINGS | keys[] as $k | "($k)#(.[$k].revision)" ' things.json
But it does not give the resul that I really want.:( Thanks in advance!
You need to escape ( :
jq -r ' .THINGS | keys[] as $k | "\($k)#\(.[$k].revision)" ' things.json

Write json from bash pipe with several variable interpolations

I have this output from a pipe
{
"pipelineName": "pipelineName-AAAAQ6UFM",
"pipelineVersion": 2,
"stageStates": [
{
"stageName": "Approval",
"inboundTransitionState": {
"enabled": true
},
"actionStates": [
{
"actionName": "Approval",
"latestExecution": {
"status": "InProgress",
"token": "aaaa-aaaa-4316-a95f-2efc51d05761"
}
}
],
"latestExecution": {
"pipelineExecutionId": "fc73f4cb-c5a9-44a8-8fc1-d7e50259f485",
"status": "InProgress"
}
}
]
}
I am trying to write a json like this
{
"pipelineName": "pipelineName-AAAAQ6UFM",
"stageName": "Approval",
"actionName": "Approval",
"token": "aaaa-aaaa-4316-a95f-2efc51d05761",
"result": {
"status": "Approved",
"summary": ""
}
}
I could maybe set two variables from the pipeoutput with the read command but I don't know how to set both of them.
token
jq -r ' .stageStates[] | select(.stageName == "Approval") | .actionStates[0].latestExecution.token'
pipelineName
jq -r '.pipelineName'
Then I might be able to write the json with the jq command.
What would be the best way to do this ?
Based on your select(.stageName == "Approval"), it would appear that you are attempting to parameterize by the "stageName", so the following might be close to what you're looking for:
"Approval" as $stage
| { pipelineName, stageName: $stage, actionName: $stage }
+ (.stageStates[]
| select(.stageName == $stage).actionStates[]
| select(.actionName == $stage)
| {token: .latestExecution.token, result: {status: "Approved", summary: ""}})
You can use just jq to create the json:
jq ' .stageName = .stageStates[0].stageName
| .actionName = .stageStates[0].actionStates[0].actionName
| .token = .stageStates[0].actionStates[0].latestExecution.token
| .result = { "status": "Approved", "summary": "" }
| del(.stageStates, .pipelineVersion)
' file.json

Json search and print

I've been trying to use jq parser to help me extract information from json files.
Here is an example snippet
{
"main_attribute": {
"name": {
"display_name": "abc"
},
"address": {
"unit": "1",
"street": "Dundas",
"suburb": "Syd",
"state": "NSW"
},
"financial_debt": {
"bank_loan": true
}
},
"secondary_attr": {
"income": {
"pretax": 100000
},
"automobile": {
"make": "Citroen",
"model": 2015,
"new": true
},
"property": {
"property_owned": 1,
"owned_since": 2000,
"first_sale": true
},
"education": {
"degree": "MS",
"graduated": 1990,
"financial_debt": {
"bank_loan": false
}
}
}
}
I need to find the blocks where "financial_debt" is true. This field could be either in the main_attribute (as a global value) or in the secondary attribute.
Expected output:
financial_debt: bank_loan on "automobile" and "property"
Can you please advise how to go about doing this search using jq?
This is by no means the most efficient way, but it is functional. It returns a boolean value specifying whether or not there is a true boolean value under the financial_debt property.
jq '[recurse | .financial_debt? | select(. != null) | recurse | booleans] | any'
tostream can be used to find paths containing "financial_debt" as follows:
tostream
| select(length==2)
| select(.[0] | contains(["financial_debt"]))
with this filter in filter.jq and data in data.json
$ jq -M -c -f filter.jq data.json
produces
[["main_attribute","financial_debt","bank_loan"],true]
[["secondary_attr","education","financial_debt","bank_loan"],false]
This intermediate result can be used along with reduce, setpath, getpath and a filter such as
. as $d
| reduce ( tostream
| select(length==2)
| select(.[0] | contains(["financial_debt"]))) as [$p,$v] (
{}
; setpath($p[:-1]; $d | getpath($p[:-1]))
)
to produce
{
"main_attribute": {
"financial_debt": {
"bank_loan": true
}
},
"secondary_attr": {
"education": {
"financial_debt": {
"bank_loan": false
}
}
}
}