如何使用Jinja2向嵌套列表追加组合字段?
为嵌套字典列表批量添加组合字段uid
问题背景
现有通过Ansible read_csv模块提取的嵌套字典列表数据集:
[ { "id": "1", "name": "apple", "quantity": "10", "type": "fruit" }, { "id": "2", "name": "orange", "quantity": "20", "type": "fruit" }, { "id": "3", "name": "carrot", "quantity": "5", "type": "veg" }, { "id": "4", "name": "beetroot", "quantity": "2", "type": "veg" } ]
需要为列表中的每个字典追加uid字段,字段值由type-name-id组合而成,预期结果如下:
[ { "uid": "fruit-apple-1", "id": "1", "name": "apple", "quantity": "10", "type": "fruit" }, { "uid": "fruit-orange-2", "id": "2", "name": "orange", "quantity": "20", "type": "fruit" }, { "uid": "veg-carrot-3", "id": "3", "name": "carrot", "quantity": "5", "type": "veg" }, { "uid": "veg-beetroot-4", "id": "4", "name": "beetroot", "quantity": "2", "type": "veg" } ]
由于列表规模较大,希望避免使用Ansible循环,改用纯Jinja实现。此前尝试的代码仅生成了uid值的扁平列表,无法保留原有嵌套结构:
- jinja_list: |- {% set uid = [] %} {% for item in fruits_csv_list.list %} {% set li = item.type + '-' + item.name + '-' + item.id %} {{uid.append(li)}} {%- endfor %} {{uid}}
解决方案
使用Jinja的字典合并+列表处理逻辑,直接生成包含uid字段的新嵌套列表,全程由Jinja处理,不触发Ansible循环:
写法一(兼容全版本Jinja2)
- set_fact: updated_fruits_list: > {% set ns = namespace(result=[]) %} {% for item in fruits_csv_list.list %} {% set updated_item = item | combine({'uid': '{}-{}-{}'.format(item.type, item.name, item.id)}) %} {% set ns.result = ns.result + [updated_item] %} {% endfor %} {{ ns.result }}
写法二(简洁高效,需Jinja2支持列表推导)
- set_fact: updated_fruits_list: "{{ fruits_csv_list.list | map('combine', {'uid': '{}-{}-{}'.format(item.type, item.name, item.id)}) | list }}"
核心逻辑说明
- 通过
combine过滤器将生成的uid键值对合并到原字典中,保留所有原有字段的同时添加新字段 - 两种写法均避免了Ansible的循环迭代,依赖Jinja的内部处理,对大规模数据更高效
- 第一种写法用
namespace变量解决Jinja循环内的变量作用域问题,确保结果能正确累积
内容的提问来源于stack exchange,提问作者diaryfolio
相关产品推荐
相关产品推荐

