I have a JSON file with some data on it, like the below one:
{
"84d0da32-c945-9844-86cc-4b4bd6100dc5": {
"UUID": "84d0da32-c945-9844-86cc-4b4bd6100dc5",
"GroupName": "TEST1",
"EntryTitle": "host1",
"Username": "sys",
"NewPassword": "@PVmkiajauauajjhfz-5/NN"
},
"test": {
"UUID": "5c3c162f-0a80-f949-85a0-afcf9aedb6c8",
"GroupName": "TEST2",
"EntryTitle": "host2",
"Username": "sys",
"NewPassword": "H7-uPz2mkaaua@ki7q?NSs?"
}
}
I am trying to filter only the field GroupName
or EntryTitle
, with json_query
but it always give null
, if I try to write all GroupName
field, it returns both.
I only want to pass for example if GroupName
is TEST2
return the EntryTitle
field.
Example of my code until now:
- name: load json data
shell: cat entries.json
register: result
- name: save json do var
set_fact:
jsondata: "{{ result.stdout | from_json }}"
- name: server name
set_fact:
servername: "{{ jsondata | json_query(jq) }}"
vars:
jq: "*.GroupName"
- name: Print
debug:
msg: "{{ item }}"
with_items:
- "{{ servername }}"
I guess your trial at a query was something like
*[?GroupName == `TEST2`].EntryTitle
This does indeed returns an empty list ([]
) as *
is an object projection, and in order to chain a projection on top of another projection, in JMESPath, you have to reset the previous projection, with a pipe expression.
Here, the query [?GroupName == `TEST2`]
is a filter projection, so you indeed have to follow the above mentioned rule by resetting the projection created by the object projection:
* | [?GroupName == `TEST2`].EntryTitle
So, you should update your server name
task accordingly:
- name: server name
set_fact:
servername: "{{ jsondata | json_query(jq) }}"
vars:
jq: "* | [?GroupName == `TEST2`].EntryTitle"
Side notes:
shell
task. If the file is on the remote node, use the slurp
module, if the file is local to the controller, use a file
lookuploop
syntax instead of the with_*
one, already. There are plenty of examples to migrate them in the documentation and the syntax usually feels more aligned across all different loops of your tasks, as the logic is expressed in filters rather than in the variation of the with_*
usedSo, if the file is on the remote node(s):
- slurp:
src: entries.json
register: entries_json
- debug:
var: >-
entries_json.content
| b64decode
| from_json
| json_query('* | [?GroupName == `TEST2`].EntryTitle | [0]')
Would yield
ok: [localhost] =>
? |-
entries_json.content
| b64decode
| from_json
| json_query('* | [?GroupName == `TEST2`].EntryTitle | [0]')
: host2
And if the file is on the controller node, then you can cut it down to a single task:
- debug:
var: >-
lookup('ansible.builtin.file', 'entries.json')
| from_json
| json_query('* | [?GroupName == `TEST2`].EntryTitle | [0]')
Would yield
ok: [localhost] =>
? |-
lookup('ansible.builtin.file', 'entries.json')
| from_json
| json_query('* | [?GroupName == `TEST2`].EntryTitle | [0]')
: host2
Extra note: the | [0]
is once again a pipe expression meant to reset the previous projection, as explained before, in order to get the element [0]
, so the first one, of the JSON array.