Reputation: 2696
Using this JSON taken from a Jenkins build api call via curl
{
"_class" : "org.jenkinsci.plugins.workflow.job.WorkflowRun",
"actions" : [
{
"_class" : "hudson.model.CauseAction",
"causes" : [
{
"_class" : "jenkins.branch.BranchIndexingCause",
"shortDescription" : "Branch indexing"
}
]
},
{
"_class" : "hudson.model.ParametersAction",
"parameters" : [ "..." ]
},
{
"_class" : "hudson.tasks.junit.TestResultAction",
"failCount" : 1,
"skipCount" : 14,
"totalCount" : 222,
"urlName" : "testReport"
}
],
"artifacts" : [ "..." ],
"result" : "UNSTABLE",
"previousBuild" : {
"number" : 98,
"url" : "<some Url>"
}
}
Why can I do jq '{result}' <fileNameWithJSON>
and get
{ "result" : "UNSTABLE" }
But I cannot do jq '{.actions[2] failCount}' <fileNameWithJSON>
or other variations such as
jq '{actions[2].failCount}'
jq '{actions[2] failCount}'
jq '{actions .[2].failCount}'
etc.
to get { "failCount" : "1" }
?
I want to grab the result
, as well as actions[2] failCount
, actions[2] skipCount
and actions[2] totalCount
to create a new JSON like this:
{ "result" : "UNSTABLE","failCount" : 1, "skipCount" : 14,"totalCount" : 222}
EDIT:
My goal was to not have to re-specify the keys in case they changed in the api. I essentially didn't want this:
{result, "failCount":.actions[2].failCount, "skipCount":.actions[2].skipCount, "totalCount": .actions[2].totalCount}
Upvotes: 0
Views: 741
Reputation: 116880
My goal was to not have to re-specify the keys in case they changed in the api.
If that is one of the main goals, you might want to consider an approach exemplified by the following, which also makes no assumption about which element of .actions
contains the information of interest:
{ result } + (.actions[] | select(has("failCount")))
With your example data, this would produce:
{
"result": "UNSTABLE",
"_class": "hudson.tasks.junit.TestResultAction",
"failCount": 1,
"skipCount": 14,
"totalCount": 222,
"urlName": "testReport"
}
If you don't want some of the extra fields, you can delete them, e.g. if you definitely do not want "_class", you can add del(._class)
to the pipeline.
Upvotes: 0
Reputation: 295679
The {}
syntax is sugar. It's intended to be used as a shortcut when you need a simple expression, but there's no reason to use that same shortened syntax when what you actually want is more interesting.
jq '
.actions[2] as $a2 | # assign second action to a variable
{ "result": .result, # refer direct to original input when appropriate...
"skipCount": $a2.skipCount, # ...or to that variable otherwise.
"failCount": $a2.failCount,
"totalCount": $a2.totalCount}
' <<<"$json"
Upvotes: 0
Reputation: 134521
jq can only copy direct fields from one object to another in object literals. It wasn't programmed to go any deeper than that though it is most certainly possible in other languages that support this kind of feature.
If your goal is to minimize the repetition of the property names, you will just have to rewrite the filter a bit.
{result} + (.actions[2] | {failCount,skipCount,totalCount})
Upvotes: 3