过滤字典列表并将新的 key:value 从循环项添加到列表中的所有字典

问题描述 投票:0回答:1

我正在尝试准备一个字典列表,其中包含从 JSON 文件接收到的所有所需数据。我已经解析了该文件,看起来不错,但我仍然需要:

  1. 向列表“package: item”中的每个字典添加新元素,其中 item 是从 with_items:“{{packages_to_import }}”获取的。这个变量是一个简单的列表,其中包含我需要处理的所有文件。

  2. 有没有办法也过滤这个列表(在同一任务中)并删除其中一个键具有空值的所有字典?我可以添加条件来执行下一个任务,但是会跳过很多项目,从而使输出的可读性较差。

我的任务:

- name: "Read JSON files"
  set_fact: 
    json_content: "{{ json_content | 
                      default([]) + ((lookup('file', item) | 
                      from_json ).transferDetails | 
                      json_query('[].{name: transferObject.summary.name, id: transferObject.summary.id, path: transferObject.contentSourceLocation}') |
                      list }}"
  with_items: "{{ packages_to_import }}"

我设法创建的当前字典:

ok: [localhost] => {
    "msg": [
        {
            "id": "123456789",
            "name": "filename1",
            "path": null
        },
        {
            "id": "1234567",
            "name": "filename2",
            "path": "/folder1/folder2"
        },
        {
            "id": "1234567",
            "name": "filename3",
            "path": "folder1"
        }
}

我想实现:

ok: [localhost] => {
    "msg": [
        {
            "id": "1234567",
            "name": "filename2",
            "path": "/folder1/folder2",
            "package: "/folder1/folder2/file2
        },
        {
            "id": "1234567",
            "name": "filename3",
            "path": "folder1",
            "package: "/folder1/file3
        }
}

编辑: packages_to_import 的结构是:

ok: [localhost] => {
    "msg": [
        "/path_to_file1/file1.json",
        "/path_to_file1/file2.json",
        "/path_to_file1/file3.json"
    ]
}


list dictionary ansible
1个回答
0
投票

给出测试文件

shell> cat /tmp/ansible/file1.json 
transferDetails:
  transferObject:
    contentSourceLocation:
    summary:
      id: 123456789
      name: filename1
shell> cat /tmp/ansible/file2.json 
transferDetails:
  transferObject:
    contentSourceLocation: /folder1/folder2
    summary:
      id: 1234567
      name: filename2
shell> cat /tmp/ansible/file3.json 
transferDetails:
  transferObject:
    contentSourceLocation: folder1
    summary:
      id: 1234567
      name: filename

公布名单

  packages_to_import:
    - /tmp/ansible/file1.json
    - /tmp/ansible/file2.json
    - /tmp/ansible/file3.json

阅读文件

    - command: cat {{ item }}
      register: out
      loop: "{{ packages_to_import }}"

公布名单

  json_content: "{{ out.results |
                    map(attribute='stdout') |
                    map('from_yaml') |
                    json_query(_query) }}"
  _query: '[].transferDetails[].{name: transferObject.summary.name,
                                 id: transferObject.summary.id,
                                 path: transferObject.contentSourceLocation}'

给出(如预期)

  json_content:
  - id: 123456789
    name: filename1
    path: null
  - id: 1234567
    name: filename2
    path: /folder1/folder2
  - id: 1234567
    name: filename3
    path: folder1

问:“将新元素

package: item
添加到列表中的每个字典中。”

A:使用文件管理器community.general.dict_kv创建新元素列表,zip列表,组合项目

  json_conten2: "{{ packages_to_import |
                    map('community.general.dict_kv', 'package') |
                    zip(json_content) |
                    map('combine') }}"

给予

  json_conten2:
  - id: 123456789
    name: filename1
    package: /tmp/ansible/file1.json
    path: null
  - id: 1234567
    name: filename2
    package: /tmp/ansible/file2.json
    path: /folder1/folder2
  - id: 1234567
    name: filename3
    package: /tmp/ansible/file3.json
    path: folder1

问:“删除所有键为空值的字典。”

A:计算有效值的数量并添加新元素

    json_conten3: "{{ json_conten2 | json_query('[].*') | map('length') |
                      map('community.general.dict_kv', 'valid') |
                      zip(json_conten2) |
                      map('combine') }}"

给予

  json_conten3:
  - id: 123456789
    name: filename1
    package: /tmp/ansible/file1.json
    path: null
    valid: 3
  - id: 1234567
    name: filename2
    package: /tmp/ansible/file2.json
    path: /folder1/folder2
    valid: 4
  - id: 1234567
    name: filename3
    package: /tmp/ansible/file3.json
    path: folder1
    valid: 4

现在,选择是微不足道的。例如,

  json_conten3 | selectattr('valid', 'eq', 4)

用于测试的完整剧本示例

- hosts: localhost

  vars:

    packages_to_import:
      - /tmp/ansible/file1.json
      - /tmp/ansible/file2.json
      - /tmp/ansible/file3.json

    json_content: "{{ out.results |
                      map(attribute='stdout') |
                      map('from_yaml') |
                      json_query(_query) }}"
    _query: '[].transferDetails[].{name: transferObject.summary.name,
                                   id: transferObject.summary.id,
                                   path: transferObject.contentSourceLocation}'

    json_conten2: "{{ packages_to_import |
                      map('community.general.dict_kv', 'package') |
                      zip(json_content) |
                      map('combine') }}"

    json_conten3: "{{ json_conten2 | json_query('[].*') | map('length') |
                      map('community.general.dict_kv', 'valid') |
                      zip(json_conten2) |
                      map('combine') }}"

  tasks:

    - command: cat {{ item }}
      register: out
      loop: "{{ packages_to_import }}"
    - debug:
        var: out

    - debug:
        var: json_content

    - debug:
        var: json_conten2

    - debug:
        var: json_conten3

    - debug:
        var: json_conten3 | selectattr('valid', 'eq', 4)
© www.soinside.com 2019 - 2024. All rights reserved.