Registering value from JSON output

20 views
Skip to first unread message

Cade Lambert

unread,
Aug 27, 2019, 3:44:16 PM8/27/19
to Ansible Project
I'm trying to register the value of a JSON object only when another JSON object is equal to a certain value, but I just can't figure out how I'd do that.

For example, this is my JSON output which is registered in the variable results_var:

"output": {
     "json": {
          "results": [
                {
                     "name": "item1"
                     "id": "26"
                 }
                {
                     "name": "item2"
                     "id": "29"
                 }
                {
                     "name": "item3"
                     "id": "10"
                 }
             ]
       }
}

What I'd like to do is place the id into a variable only when the name matches a string.

I was trying something like this but it fails because the variable is a list.

  - set_fact:
      host_id: "{{ item.id }}"
    when: item.name == "item2"
    loop: "{{ results_var.output.json.results }}"
    

Kai Stian Olstad

unread,
Aug 27, 2019, 3:54:03 PM8/27/19
to ansible...@googlegroups.com
On 27.08.2019 21:44, Cade Lambert wrote:
> I'm trying to register the value of a JSON object only when another JSON
> object is equal to a certain value, but I just can't figure out how I'd do
> that.
>
> For example, this is my JSON output which is registered in the variable
> results_var:
>
> "output": {
> "json": {
> "results": [
> {
> "name": "item1"
> "id": "26"
> }
> {
> "name": "item2"
> "id": "29"
> }
> {
> "name": "item3"
> "id": "10"
> }
> ]
> }
> }

This output looks wired, it's missing commas after } in the list.


> What I'd like to do is place the id into a variable only when the name
> matches a string.
>
> I was trying something like this but it fails because the variable is a
> list.
>
> - set_fact:
> host_id: "{{ item.id }}"
> when: item.name == "item2"
> loop: "{{ results_var.output.json.results }}"

You should always provide the exact error message and probably the all the code too, at fist glance I don't see anything wrong with the code.


--
Kai Stian Olstad

Vladimir Botka

unread,
Aug 27, 2019, 4:06:04 PM8/27/19
to Cade Lambert, ansible...@googlegroups.com
On Tue, 27 Aug 2019 12:44:15 -0700 (PDT)
Cade Lambert <crl...@gmail.com> wrote:

> [...]
> "output": {
> "json": {
> "results": [
> {
> "name": "item1"
> "id": "26"
> }
> {
> "name": "item2"
> "id": "29"
> }
> {
> "name": "item3"
> "id": "10"
> }
> ]
> }
> }
>
> What I'd like to do is place the id into a variable only when the name
> matches a string.
>
> I was trying something like this but it fails because the variable is a
> list.
>
> - set_fact:
> host_id: "{{ item.id }}"
> when: item.name == "item2"
> loop: "{{ results_var.output.json.results }}"

json_query does the job. For example

- set_fact:
host_id: "{{ json.results|json_query('[?name==`item2`].id') }}"

if the data is properly structured.

json:
results:
- id: '26'
name: item1
- id: '29'
name: item2
- id: '10'
name: item3

Cheers,

-vlado

Cade Lambert

unread,
Aug 28, 2019, 11:04:17 AM8/28/19
to Ansible Project
Ok, I guess a little background would help.  I'm using the uri module to retrieve a list of hosts in an inventory from our Tower server.  It returns the JSON output below. I've paired it down to just the pieces I care about.  There are two servers in this inventory. I'd like to retrieve the id based on the server name.

ok: [localhost] => {
    "host_list.json.results": [
        {
            "ansible_facts_modified": null,
            "created": "2019-08-27T18:50:09.132071Z",
            "description": "",
            "enabled": true,
            "has_active_failures": false,
            "has_inventory_sources": false,
            "id": 799,
            "insights_system_id": null,
            "instance_id": "",
            "inventory": 18,
            "last_job": null,
            "last_job_host_summary": null,
            "modified": "2019-08-27T18:50:09.132085Z",
            "name": "server1",            
        },
        {
            "ansible_facts_modified": "2019-08-28T14:41:17.846100Z",
            "created": "2019-08-26T19:28:55.187225Z",
            "description": "",
            "enabled": true,
            "has_active_failures": false,
            "has_inventory_sources": false,
            "id": 790,
            "insights_system_id": null,
            "instance_id": "",
            "inventory": 18,
            "last_job": 7879,
            "last_job_host_summary": 10273,
            "modified": "2019-08-28T14:41:17.846235Z",
            "name": "server2",
            
        }
    ]
}

I tried json_query:

- set_fact:
     host_id: "{{ host_list.json.results|json_query('[?name == 'server2'].id') }}"

It threw the following error:
fatal: [localhost]: FAILED! => {"msg": "template error while templating string: expected token ',', got 'server2'. String: {{ host_list.json.results|json_query('[?name == 'server2'].id') }}"}

Vladimir Botka

unread,
Aug 28, 2019, 11:27:22 AM8/28/19
to Cade Lambert, ansible...@googlegroups.com
On Wed, 28 Aug 2019 08:04:16 -0700 (PDT)
Cade Lambert <crl...@gmail.com> wrote:

> Ok, I guess a little background would help.
> [...]
> I tried json_query:
>
> - set_fact:
> host_id: "{{ host_list.json.results|json_query('[?name == 'server2'].id') }}"
>
> It threw the following error:
> fatal: [localhost]: FAILED! => {"msg": "template error while templating
> string: expected token ',', got 'server2'. String: {{
> host_list.json.results|json_query('[?name == 'server2'].id') }}"}

The error is caused by your "improvement". The query works fine when you keep
the backticks "`" that wrap the argument (both double and single-quotes have
already been used elsewhere in the string). The tasks below

- set_fact:
host_id: "{{ results|json_query('[?name==`server2`].id') }}"
- debug:
var: host_id

give

"host_id": [
790
]

Cheers,

-vlado

Cade Lambert

unread,
Aug 28, 2019, 11:35:24 AM8/28/19
to Ansible Project
Ah, ok, I missed that those were backticks.  So because we used double-quotes to encompass the whole argument, and single-quotes to encompass the json_query argument, we cannot use single-quotes again to encompass the search string. We need to use something else, in this case backticks, to distinguish the search string?

Vladimir Botka

unread,
Aug 28, 2019, 12:25:18 PM8/28/19
to Cade Lambert, ansible...@googlegroups.com
Right. It's possible to avoid them and declare a variable for this purpose.

- set_fact:
host_id: "{{ results|json_query(query) }}"
vars:
query: "[?name=='server2'].id"

Cade Lambert

unread,
Aug 28, 2019, 1:16:53 PM8/28/19
to Ansible Project
Great, thanks for the help.
Reply all
Reply to author
Forward
0 new messages