【问题标题】:How to make a specific dict in Ansible from json output如何从 json 输出在 Ansible 中制作特定的 dict
【发布时间】:2022-11-11 00:36:45
【问题描述】:

我有一个在 2 个或更多 url 上运行的 Ansible 作业。每个 url 返回具有不同值的相同变量。这是作业的 JSON 数据注册表:

{
  "msg": {
    "results": [
      {
        "url": "http://0.0.0.1:xxx1",
        "othervar": "othervar",
        "othervar2": "othervar2",
        "json": {
          "messages": [
            {
              "message": "This is message number 1",
              "message2": "This is message2 number 1"
            },
            {
                "message": "This is message number 2",
                "message2": "This is message2 number 2"
            },
            {
                "message": "This is message number 3",
                "message2": "This is message2 number 3"
            }
          ]
        }
      },
      {
        "url": "http://0.0.0.2:xxx2",
        "othervar": "othervar",
        "othervar2": "othervar2",
        "json": {
          "messages": [
            {
              "message": "This is message number 1",
              "message2": "This is message2 number 1"
            },
            {
                "message": "This is message number 2",
                "message2": "This is message2 number 2"
            },
            {
                "message": "This is message number 3",
                "message2": "This is message2 number 3"
            }
          ]
        }
      }
    ]
  }
}

我想制作一个仅包含 url 变量以及 messagemessage2 变量的特定字典。对于预期的结果,我有 2 个选项:

选项1:

"message": [
    {
      "url": "http://0.0.0.1:xxx1",
      "content": [
          {
            "message": "This is message number 1",
            "message2": "This is message2 number 1"
          },
          {
              "message": "This is message number 2",
              "message2": "This is message2 number 2"
          },
          {
              "message": "This is message number 3",
              "message2": "This is message2 number 3"
          }
        ]
    },
    {
        "url": "http://0.0.0.2:xxx2",
        "content": [
            {
              "message": "This is message number 1",
              "message2": "This is message2 number 1"
            },
            {
                "message": "This is message number 2",
                "message2": "This is message2 number 2"
            },
            {
                "message": "This is message number 3",
                "message2": "This is message2 number 3"
            }
          ]
      }

选项2:

"message": [
  {
    "url": "http://0.0.0.0:xxx1",
    "message": "This is message number 1",
    "message2": "This is message2 number 1"
  },
  {
    "url": "http://0.0.0.0:xxx1",
    "message": "This is message number 2",
    "message2": "This is message2 number 2"
  },
  {
    "url": "http://0.0.0.0:xxx1",
    "message": "This is message number 2",
    "message2": "This is message2 number 2"
  },
  {
    "url": "http://0.0.0.0:xxx2",
    "message": "This is message number 1",
    "message2": "This is message2 number 1"
  },
  {
    "url": "http://0.0.0.0:xxx2",
    "message": "This is message number 2",
    "message2": "This is message2 number 2"
  },
  {
    "url": "http://0.0.0.0:xxx2",
    "message": "This is message number 2",
    "message2": "This is message2 number 2"
  }
]

我能够获取每个变量(仅 url、仅消息、仅 message2)但我如何将它们合并到选项 1 或选项 2 之类的字典中?

【问题讨论】:

    标签: json dictionary ansible


    【解决方案1】:

    最简单的方法是从最接近原始数据的选项 1 开始。例如,您可以在游戏中将其声明为 var:

        my_results: "{{ results | json_query('[].{"url": url, "content": json.     messages}') }}"
    

    请注意,json_query 需要 community.general 集合(如果您安装了 ansible 元包,通常可用)和 pip install jmespath

    这给出(调试上述变量):

    TASK [debug] *******************************************************************
    ok: [localhost] => {
        "my_results": [
            {
                "content": [
                    {
                        "message": "This is message number 1",
                        "message2": "This is message2 number 1"
                    },
                    {
                        "message": "This is message number 2",
                        "message2": "This is message2 number 2"
                    },
                    {
                        "message": "This is message number 3",
                        "message2": "This is message2 number 3"
                    }
                ],
                "url": "http://0.0.0.1:xxx1"
            },
            {
                "content": [
                    {
                        "message": "This is message number 1",
                        "message2": "This is message2 number 1"
                    },
                    {
                        "message": "This is message number 2",
                        "message2": "This is message2 number 2"
                    },
                    {
                        "message": "This is message number 3",
                        "message2": "This is message2 number 3"
                    }
                ],
                "url": "http://0.0.0.2:xxx2"
            }
        ]
    }
    

    从那里开始,如果您需要循环看起来像选项 2 的结构,使用 subelements 查找很容易实现:

        - name: loop on a structure looking like option 2
          debug:
            msg:
              - "url is {{ item.0.url }}"
              - "message one is {{ item.1.message }}"
              - "message two is {{ item.1.message2 }}"
          loop: "{{ q('subelements', my_results, 'content') }}"
          loop_control:
            label: "{{ item.0.url }}"
    

    这使:

    TASK [loop on a structure looking like option 2] *******************************
    ok: [localhost] => (item=item.0.url) => {
        "msg": [
            "url is http://0.0.0.1:xxx1",
            "message one is This is message number 1",
            "message two is This is message2 number 1"
        ]
    }
    ok: [localhost] => (item=item.0.url) => {
        "msg": [
            "url is http://0.0.0.1:xxx1",
            "message one is This is message number 2",
            "message two is This is message2 number 2"
        ]
    }
    ok: [localhost] => (item=item.0.url) => {
        "msg": [
            "url is http://0.0.0.1:xxx1",
            "message one is This is message number 3",
            "message two is This is message2 number 3"
        ]
    }
    ok: [localhost] => (item=item.0.url) => {
        "msg": [
            "url is http://0.0.0.2:xxx2",
            "message one is This is message number 1",
            "message two is This is message2 number 1"
        ]
    }
    ok: [localhost] => (item=item.0.url) => {
        "msg": [
            "url is http://0.0.0.2:xxx2",
            "message one is This is message number 2",
            "message two is This is message2 number 2"
        ]
    }
    ok: [localhost] => (item=item.0.url) => {
        "msg": [
            "url is http://0.0.0.2:xxx2",
            "message one is This is message number 3",
            "message two is This is message2 number 3"
        ]
    }
    

    这是完整测试的剧本:

    ---
    - hosts: localhost
      gather_facts: false
    
      vars:
        # Your orig data minified
        results: [{"url":"http://0.0.0.1:xxx1","othervar":"othervar","othervar2":"othervar2","json":{"messages":[{"message":"This is message number 1","message2":"This is message2 number 1"},{"message":"This is message number 2","message2":"This is message2 number 2"},{"message":"This is message number 3","message2":"This is message2 number 3"}]}},{"url":"http://0.0.0.2:xxx2","othervar":"othervar","othervar2":"othervar2","json":{"messages":[{"message":"This is message number 1","message2":"This is message2 number 1"},{"message":"This is message number 2","message2":"This is message2 number 2"},{"message":"This is message number 3","message2":"This is message2 number 3"}]}}]
    
        my_results: "{{ results | json_query('[].{"url": url, "content": json.messages}') }}"
    
      tasks:
        - name: debug my_results var to check
          debug:
            var: my_results
    
        - name: loop on a structure looking like option 2
          debug:
            msg:
              - "url is {{ item.0.url }}"
              - "message one is {{ item.1.message }}"
              - "message two is {{ item.1.message2 }}"
          loop: "{{ q('subelements', my_results, 'content') }}"
          loop_control:
            label: item.0.url
    

    【讨论】:

      【解决方案2】:

      以下代码加载您的输入 json,然后使用您在选项 1 中要求的结构创建一个新数组,方法是在迭代消息列表时创建新项目:

      ---
      - name: Playbook for infinispan Hosts
        hosts: localhost
        tasks:
          - name: load json from file
            shell: cat test.json
            register: result
          - name: save the input json data to a variable
            set_fact:
              jsondata: "{{ result.stdout | from_json }}"
          - name: display the input dict
            debug:
              var: jsondata
          - name: parse the json into new array
            set_fact:
              message: "{{ message|default([]) + [ { 'url': item.url, 'content': item.json.messages }  ] }}"
            loop: "{{ jsondata.msg.results }}"
          - name: display the resulting data structure
            debug:
              var: message
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-25
        • 1970-01-01
        • 1970-01-01
        • 2018-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多