什么时候在Ansible中使用from_json过滤器? [英] When to use from_json filter in Ansible?

查看:86
本文介绍了什么时候在Ansible中使用from_json过滤器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

何时应使用from_json 过滤器在Ansible中?

When should I use the from_json filter in Ansible?

我发现使用它有时有效果,有时没有效果.

I found out that using it sometimes has and sometimes have no effect.

请考虑以下示例,该示例说明了我得到的不一致之处.

Please consider the following example which illustrates the inconsistency I am getting.

以相反的顺序包括:问题-预期结果-实际结果-剧本-数据.数据取自此问题,而剧本则基于

Included in reverse order are: the questions - expected result - actual result - the playbook - the data. The data is taken from this question and the playbook is based on this answer.

  • 问题:

  • The question(s):

为什么将以下表达式的左部分(在json_query之前)存储在变量中,然后在变量上使用json_query导致对表达式的求值方式不同?

Why storing the left part (before json_query) of the following expression in a variable and then using json_query on the variable causes the expression to be evaluated differently?

"{{ lookup('file','test.json') | json_query(query) }}"

为什么添加from_json过滤器会改变结果(但如果处理变量则不会):

Why does adding from_json filter alter the results (but does not if processing a variable):

"{{ lookup('file','test.json') | from_json | json_query(query) }}"

  • 预期结果:

  • Expected result:

    最后四个任务应该给出相同的结果.另外,最后两个任务应该得到与前两个任务相同的结果.

    Last four tasks should give the same result. Alternatively, last two tasks should give the same result as previous two tasks.

    实际结果(仅最后四个任务):

    Actual result (last four tasks only):

    一个任务的结果不同.

    TASK [This query is run against lookup value with from_json stored in a variable] ***
    ok: [localhost] => {
        "msg": [
            678
        ]
    }
    
    TASK [This query is run against lookup value without from_json stored in a variable] ***
    ok: [localhost] => {
        "msg": [
            678
        ]
    }
    
    TASK [This query is run directly against lookup value with from_json] **********
    ok: [localhost] => {
        "msg": [
            678
        ]
    }
    
    TASK [This query is run directly against lookup value without from_json - the result is empty - why?] ***
    ok: [localhost] => {
        "msg": ""
    }
    

  • 剧本:

  • The playbook:

    ---
    - hosts: localhost
      gather_facts: no
      connection: local
      tasks:   
        - set_fact:
            from_lookup_with_from_json: "{{ lookup('file','test.json') | from_json }}"
    
        - set_fact:
            from_lookup_without_from_json: "{{ lookup('file','test.json') }}"
    
        - name: Save the lookup value stored in a variable in a file for comparison
          copy: content="{{ from_lookup_with_from_json }}" dest=./from_lookup_with_from_json.txt
    
        - name: Save the lookup value stored in a variable in a file for comparison (they are the same)
          copy: content="{{ from_lookup_without_from_json }}" dest=./from_lookup_without_from_json.txt
    
        - name: This query is run against lookup value with from_json stored in a variable
          debug: msg="{{ from_lookup_with_from_json | json_query(query) }}"
          vars:
            query: "Foods[].{id: Id, for: (Tags[?Key=='For'].Value)[0]} | [?for=='Tigger'].id"
    
        - name: This query is run against lookup value without from_json stored in a variable
          debug: msg="{{ from_lookup_without_from_json | json_query(query) }}"
          vars:
            query: "Foods[].{id: Id, for: (Tags[?Key=='For'].Value)[0]} | [?for=='Tigger'].id"
    
        - name: This query is run directly against lookup value with from_json
          debug: msg="{{ lookup('file','test.json') | from_json | json_query(query) }}"
          vars:
            query: "Foods[].{id: Id, for: (Tags[?Key=='For'].Value)[0]} | [?for=='Tigger'].id"
    
        - name: This query is run directly against lookup value without from_json - the result is empty - why?
          debug: msg="{{ lookup('file','test.json') | json_query(query) }}"
          vars:
            query: "Foods[].{id: Id, for: (Tags[?Key=='For'].Value)[0]} | [?for=='Tigger'].id"
    

  • 数据(test.json):

    { "Foods" :
      [ { "Id": 456
        , "Tags":
          [ {"Key":"For", "Value":"Heffalump"}
          , {"Key":"Purpose", "Value":"Food"}
          ]
        }
      , { "Id": 678
        , "Tags":
          [ {"Key":"For", "Value":"Tigger"}
          , {"Key":"Purpose", "Value":"Food"}
          ]
        }
      , { "Id": 911
        , "Tags":
          [ {"Key":"For", "Value":"Roo"}
          , {"Key":"Purpose", "Value":"Food"}
          ]
        }
      ]
    }
    

  • 推荐答案

    json_query需要Python对象(dict)作为输入,如果将它与字符串一起输入,它将给出空字符串作为结果.

    json_query requires Python object (dict) as input, if you feed it with string, it gives empty string as result.

    由于Ansible模板引擎的棘手工作,您得到了不同的结果.
    我绝对应该在我的网站上写一篇关于它的文章...

    You get different result because of Ansible templating engine tricky work.
    I should definitely write a post about it on my site...

    评估jijna2表达式后,Ansible尝试将复杂类型转换为Python对象(如dict或list).请参阅我的其他答案.

    After evaluating jijna2 expression Ansible try to cast complex types to Python objects (like dict or list). See my other answer.

    在您的情况下:

    1.

    - set_fact:
        from_lookup_with_from_json: "{{ lookup('file','test.json') | from_json }}"
    

    from_lookup_with_from_json是字典,因为您使用from_json过滤器将JSON字符串从文件手动转换为字典.

    from_lookup_with_from_json is a dict, because you manually convert JSON-string from file to dict with from_json filter.

    2.

    - set_fact:
        from_lookup_without_from_json: "{{ lookup('file','test.json') }}"
    

    from_lookup_with_from_json成为字典,因为当jinja2表达式以}}结尾时,Ansible会将其转换.因此实际上from_json作为链中的最后一个过滤器实际上是不必要的.

    from_lookup_with_from_json becomes dict, because Ansible converts it when jinja2 expression ends with }}. So from_json is actually unnecessary as the last filter in chain.

    3.

      debug: msg="{{ lookup('file','test.json') | from_json | json_query(query) }}"
    

    同样,您在此处手动转换JSON字符串.因此json_query获取dict作为输入.

    Again, you manually convert JSON-string here. So json_query get dict as input.

    4.

      debug: msg="{{ lookup('file','test.json') | json_query(query) }}"
    

    在这种情况下,您将JSON字符串(不是dict)作为输入输入到json_query过滤器.由于一切都发生在一个jinja2表达式中,因此Ansible不会尝试在两者之间进行任何转换.

    In this case you feed JSON-string (not dict) as input to json_query filter. As everything happens inside one jinja2 expression, Ansible doesn't attempt to convert anything in between.

    您还可以通过以下方式使用变量获取空字符串结果:

    You can also get empty string result with a variable this way:

    - set_fact:
        from_lookup_force_string: "{{ lookup('file','test.json') | string }}"
    

    在这种情况下,from_lookup_force_string不会被Ansible模板引擎转换,并且json_query会给您空的响应.

    In this case from_lookup_force_string will not be converted by Ansible tempating engine, and json_query will give you empty response on it.

    这篇关于什么时候在Ansible中使用from_json过滤器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆