Registering value from JSON output

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 }}”

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.

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

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’) }}”}

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

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?

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"

Great, thanks for the help.