I have been stuck to get a particular json object if the value of a key matches a variable (string).
My json file looks like this:
"totalRecordsWithoutPaging": 1234,
"jobs": [
{
"jobSummary": {
"totalNumOfFiles": 0,
"jobId": 8035,
"destClientName": "BOSDEKARLSSP010",
"destinationClient": {
"clientId": 10,
"clientName": "BOSDEKARLSSP010"
}
}
},
{
"jobSummary": {
"totalNumOfFiles": 0,
"jobId": 9629,
"destClientName": "BOSDEKARLSSP006",
"destinationClient": {
"clientId": 11,
"clientName": "BOSDEKARLSSP006"
}
}
},
.....
]
}
I read this json with result: "{{ lookup('file','CVExport-short.json') | from_json }}"
and I can get only one value of destClientName
key with the following code:
- name: Iterate JSON
set_fact:
app_item: "{{ item.jobSummary }}"
with_items: "{{ result.jobs }}"
register: app_result
- debug:
var: app_result.results[0].ansible_facts.app_item.destClientName
My goal is to get the value of jobId
if the value of destClientName
matches some other variable or string in any jobSummary
.
I don't still have much knowledge in Ansible. So, any help would be much appreciated.
Update
Ok, I have found one solution.
- name: get job ID
set_fact:
job_id: "{{ item.jobSummary.jobId }}"
with_items: "{{ result.jobs}}"
when: item.jobSummary.destClientName == '{{ target_vm }}'
- debug:
msg: "{{job_id}}"
But I think there might be a better solution than this. Any idea how?
Ansible's json_query filter let's you perform complex filtering of JSON documents by applying JMESPath expressions. Rather than looping over the jobs in the the result, you can get the information you want in a single step.
We want to query all jobs in which have a destClientName
that matches the value in target_vm
. Using literal values, the expression yielding that list of jobs would look like this:
jobs[?jobSummary.destClientName == `BOSDEKARLSSP006`]
The result of this, when applied to your sample data, would be:
[
{
"jobSummary": {
"totalNumOfFiles": 0,
"jobId": 9629,
"destClientName": "BOSDEKARLSSP006",
"destinationClient": {
"clientId": 11,
"clientName": "BOSDEKARLSSP006"
}
}
}
]
From this result, you want to extract the jobId
, so we rewrite the expression like this:
jobs[?jobSummary.destClientName == `BOSDEKARLSSP006`]|[0].jobSummary.jobId
Which gives us:
9629
To make this work in a playbook, you'll want to replace the literal hostname in this expression with the value of your target_vm
variable. Here's a complete playbook that demonstrates the solution:
---
- hosts: localhost
gather_facts: false
# This is just the sample data from your question.
vars:
target_vm: BOSDEKARLSSP006
results:
totalRecordsWithoutPaging: 1234
jobs:
- jobSummary:
totalNumOfFiles: 0
jobId: 8035
destClientName: BOSDEKARLSSP010
destinationClient:
clientId: 10
clientName: BOSDEKARLSSP010
- jobSummary:
totalNumOfFiles: 0
jobId: 9629
destClientName: BOSDEKARLSSP006
destinationClient:
clientId: 11
clientName: BOSDEKARLSSP006
tasks:
- name: get job ID
set_fact:
job_id: "{{ results|json_query('jobs[?jobSummary.destClientName == `{}`]|[0].jobSummary.jobId'.format(target_vm)) }}"
- debug:
var: job_id
Update re: your comment
The {}
in the expression is a Python string formatting sequence that
is filled in by the call to .format(target_vm)
. In Python, the
expression:
'The quick brown {} jumped over the lazy {}.'.format('fox', 'dog')
Would evaluate to:
The quick brown fox jumped over the lazy dog.
And that's exactly what we're doing in that set_fact
expression. I
could instead have written:
job_id: "{{ results|json_query('jobs[?jobSummary.destClientName == `' ~ target_vm ~ '`]|[0].jobSummary.jobId') }}"
(Where ~
is the Jinja stringifying concatenation operator)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With