Stack Exchange
Get specific key/value from a nested dictionary based on another key/value
Just started working with Ansible and JSON dictionary data. I am trying to process the following dictionary using a jmesquery:
{
  "Entities": [
    {
      "MetaData": {
        "NumDiscoveredWorkloads": 20,
        "NumMigratedWorkloads": 1,
        "UUID": "uuid1234567890"
      },
      "Spec": {
        "Type": "VMWARE_ESXI_VCENTER",
        "UUID": "uuid1234567890"
      }
    },
    {
      "MetaData": {
        "NumDiscoveredWorkloads": 40,
        "UUID": "uuid1234567891"
      },
      "Spec": {
        "Type": "AOS_PC",
        "UUID": "uuid1234567891"
      }
    }
  ],
  "MetaData": {
    "Count": 2
  }
}

I want to find the value for the UUID of the ESXi item. I created the following Ansible code:
- name: "Get ESXiUUID"
  var:
    jmesquery: "Entities[*].Spec[?Type==`VMWARE_ESXI_VCENTER`].UUID"
  set_fact:
    move_providers_filtered: "{{ move_providers_details_content | json_query(jmesquery) }}"

But this does not work. I get strange errors from Ansible. Been checking the web for a day now, but nothing I tried solves the error. Can anybody tell me what I am doing wrong and how to solve this? Thanks for any support

Given the data
  providers:
    Entities:
      - MetaData:
          NumDiscoveredWorkloads: 20
          NumMigratedWorkloads: 1
          UUID: uuid1234567890
        Spec:
          Type: VMWARE_ESXI_VCENTER
          UUID: uuid1234567890
      - MetaData:
          NumDiscoveredWorkloads: 40
          UUID: uuid1234567891
        Spec:
          Type: AOS_PC
          UUID: uuid1234567891

The query below
  provider: "{{ providers.Entities|json_query(jmesquery) }}"
  jmesquery: "[].Spec | [?Type==`VMWARE_ESXI_VCENTER`].UUID"

gives
  provider:
  - uuid1234567890



Example of a complete playbook for testing
- hosts: localhost

  vars:

    providers:
      Entities:
      - MetaData:
          NumDiscoveredWorkloads: 20
          NumMigratedWorkloads: 1
          UUID: uuid1234567890
        Spec:
          Type: VMWARE_ESXI_VCENTER
          UUID: uuid1234567890
      - MetaData:
          NumDiscoveredWorkloads: 40
          UUID: uuid1234567891
        Spec:
          Type: AOS_PC
          UUID: uuid1234567891

    provider: "{{ providers.Entities|json_query(jmesquery) }}"
    jmesquery: "[].Spec | [?Type==`VMWARE_ESXI_VCENTER`].UUID"

  tasks:

    - debug:
        var: provider



I do not get an error if I correct your obvious typo (var: -> vars:), but you did not include the "strange errors" that you received so I don't know if that was the source.
I would not use JMESPath for this at all; most Ansible data manipulation can be done with pure Jinja, instead of introducing yet another thing to learn.
- hosts: localhost
  vars:
    move_providers_details_content:
      Entities:
        - Spec:
            Type: VMWARE_ESXI_VCENTER
            UUID: uuid1234567890
        - Spec:
            Type: AOS_PC
            UUID: uuid1234567891
    move_providers_filtered: "{{ (move_providers_details_content.Entities | selectattr('Spec.Type', '==', 'VMWARE_ESXI_VCENTER') | first).Spec.UUID }}"
  tasks:
    - name: Get ESXi UUID
      debug:
        msg: "{{ move_providers_filtered }}"

This uses selectattr() to filter on the attribute that we want to match, then just accesses the attributes as normal.
TASK [Get ESXi UUID] ***********************************************************
ok: [localhost] => {
    "msg": "uuid1234567890"
}


Thanks! Your solution works fine. Feel a bit stupid because of the type :-) I will also try the solution below, since I also want to understand the JMESpath logic.
