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

查看:80
本文介绍了何时在 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.

倒序包括:问题-预期结果-实际结果-剧本-数据.数据取自this question,剧本基于这个答案.

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.

  • 问题:

为什么将以下表达式的左侧部分(在 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 是一个 dict,因为您使用 from_json 过滤器手动将 JSON 字符串从文件转换为 dict.

    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 变成 dict,因为 Ansible 在 jinja2 表达式以 }} 结尾时转换它.所以 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天全站免登陆