Search code examples
jsonansiblejson-query

Ansible json_query() with variable as key


I have following JSON input:

{
  "a goo": {
      "link": "google.com"
  }, 
  "b ms": {
      "link": "microsoft.com"
  }, 
  "c amz": {
    "link": "amazon.com"
  }
}

I'd like get the link string ("google.com"…) according to variable {{ target }} Content of {{ target }} variable will contains one of the "a goo", "b ms", "c amz" string.

Something like:

- name:
  set_fact:
    target: "c amz"
- debug:
    msg: "{{ input.json | json_query('{{ target }}'.link) }}"

Which should show:

   msg: "amazon.com"

Thank you for the advice.

+FE


Solution

  • Several problems in your expression:

    1. In jmespath, identifiers are quoted with double quotes. Single quotes are used for strings. See jmespath specification.
    2. The entire jmespath expression you pass to json_query should be a yaml/jinja2 string. As you wrote it, .link will be interpreted as a jinja2/yaml var identifier.
    3. You must not imbricate the jinja2 template markers ({{ X }}). Moreover, in your current expression, '{{ target }}' is literally interpreted as a string not a variable to expand to its value.

    The following playbook demonstrates one way to fix your current playbook and to acheive your requirement:

    ---
     - hosts: localhost
       gather_facts: false
    
       vars:
         input:
           json: { 
             "a goo": { 
               "link": "google.com"
             },
             "b ms": { 
               "link": "microsoft.com"
             },
             "c amz": { 
               "link": "amazon.com"
             } 
           } 
    
       tasks:
         - name: Debug the var we want to show
           vars:
             target: "c amz"
           debug:
             msg: "{{ input.json | json_query('\"' + target + '\".link') }}"
    

    Which gives:

    $ ansible-playbook play.yml 
    
    PLAY [localhost] ***************************************************************************************************************************************************************
    
    TASK [Debug the var we want to show] *******************************************************************************************************************************************
    ok: [localhost] => {
        "msg": "amazon.com"
    }
    
    PLAY RECAP *********************************************************************************************************************************************************************
    localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0