需要将目标文件中字典中的值替换为源文件中字典中的值

Need to replace value in dictionary in destination file with the value in the dictionary in source file

我一直在尝试用源 JSON 文件中字典中的值更新目标 json 中字典中的值。以下是源和目标 JSON 文件的示例:

源文件:

[
        {
                "key": "MYSQL",
                "value": "456"
        },
        {
                "key": "RDS",
                "value": "123"
        }
]

目标文件:

[
        {
                "key": "MYSQL",
                "value": "100"
        },
        {
                "key": "RDS",
                "value": "111"
        },
        {
                "key": "DB1",
                "value": "TestDB"
        },
        {
                "key": "OS",
                "value": "EX1"
        }
]

运行 Ansible 剧本后目标文件中的预期:

[
        {
                "key": "MYSQL",
                "value": "**456**"
        },
        {
                "key": "RDS",
                "value": "**123**"
        },
        {
                "key": "DB1",
                "value": "TestDB"
        },
        {
                "key": "OS",
                "value": "EX1"
        }
]

下面是我到目前为止尝试过的剧本,但这只会更新硬编码的值:

- hosts: localhost
  tasks:

  - name: Parse JSON
    shell: cat Source.json
    register: result

  - name: Save json data to a variable
    set_fact:
      jsondata: "{{result.stdout | from_json}}"

  - name: Get key names
    set_fact:
      json_key: "{{ jsondata | map(attribute='key') | flatten }}"

  - name: Get Values names
    set_fact:
      json_value: "{{ jsondata | map(attribute='value') | flatten }}"

  # Trying to update the destination file with only the values provided in source.json
  - name: Replace values in json
    replace:
      path: Destination.json
      regexp: '"{{ item }}": "100"'
      replace: '"{{ item }}": "456"'
    loop:
    - value

主要目标是用 [=33 中提供的 value 更新 destination.json 中的 value =].

如果不知道目标文件的结构,就很难使用正则表达式。
我建议您将目标文件加载到变量中,进行更改并将变量的内容保存到文件中。

此解决方案可以完成工作:

- hosts: localhost
  tasks:

    - name: Parse JSON
      set_fact:
        source: "{{ lookup('file', 'source.json') | from_json }}"
        destination: "{{ lookup('file', 'destination.json') | from_json }}"

    - name: create new json
      set_fact:
        json_new: "{{ json_new | d([]) + ([item] if _rec == [] else [_rec]) | flatten }}"
      loop: "{{ destination }}"
      vars:
        _rec: "{{ source | selectattr('key', 'equalto', item.key) }}"


    - name: save new json
      copy:
        content: "{{ json_new | to_nice_json }}"
        dest: dest_new.json

结果 -> dest_new.json:

ok: [localhost] => {
    "msg": [
        {
            "key": "MYSQL",
            "value": "456"
        },
        {
            "key": "RDS",
            "value": "123"
        },
        {
            "key": "DB1",
            "value": "TestDB"
        },
        {
            "key": "OS",
            "value": "EX1"
        }
    ]
}

在 Ansible 中,一对 key/value 倾向于使用过滤器 dict2items and items2dict 来处理。这些过滤器可以处理您的用例。

逻辑如下:

  • 读取两个文件
  • 将两个文件转换为字典,dict2items
  • 合并两个词典,使用 combine 过滤器
  • 使用 items2dict
  • 将字典转换回列表
  • 将JSON中的结果转回文件

鉴于剧本:

- hosts: localhost
  gather_facts: no

  tasks:
    - shell: cat Source.json
      register: source

    - shell: cat Destination.json
      register: destination

    - copy:
        content: "{{ 
            destination.stdout | from_json | items2dict | 
            combine(
              source.stdout | from_json | items2dict
            ) | dict2items | to_nice_json
          }}"
        dest: Destination.json

我们最终得到 Destination.json 包含:

[
    {
        "key": "MYSQL",
        "value": "456"
    },
    {
        "key": "RDS",
        "value": "123"
    },
    {
        "key": "DB1",
        "value": "TestDB"
    },
    {
        "key": "OS",
        "value": "EX1"
    }
]