如何在Ansible的Jinja2模板中查询复杂JSON的指定字段?
在Ansible中用Jinja2遍历复杂JSON树,筛选motor中date<2001的name和id
针对结构不固定、包含大量随机子节点的复杂JSON,你需要通过递归遍历整个节点树来定位符合条件的条目。下面是具体实现方案:
核心思路
因为JSON结构存在随机子节点,无法通过固定路径(比如cars[0].Ford[0].vehicle.motor...)查询,必须递归遍历所有节点:
- 遍历过程中记录遇到的
name值 - 记录每个
date对应的同级id值 - 当发现
date数值小于2001时,关联之前记录的name和当前id输出
实现代码
1. 编写Jinja2递归宏(模板文件:filter_motor.j2)
{%- macro find_motor_entries(node, current_name=None, current_id=None) %} {%- set results = [] %} {%- if node is mapping %} {%- for key, value in node.items() %} {%- if key == 'name' %} {%- set current_name = value %} {%- elif key == 'id' %} {%- set current_id = value %} {%- elif key == 'date' and value|int < 2001 %} {%- if current_name and current_id %} {%- do results.append(current_name ~ ' & ' ~ current_id) %} {%- endif %} {%- endif %} {%- if value is iterable and value is not string %} {%- set sub_results = find_motor_entries(value, current_name, current_id) %} {%- if sub_results %} {%- do results.extend(sub_results) %} {%- endif %} {%- endif %} {%- endfor %} {%- elif node is sequence %} {%- for item in node %} {%- set sub_results = find_motor_entries(item, current_name, current_id) %} {%- if sub_results %} {%- do results.extend(sub_results) %} {%- endif %} {%- endfor %} {%- endif %} {{ results }} {%- endmacro %} {%- set matched_entries = find_motor_entries(complex_json) %} {%- for entry in matched_entries %} {{ entry }} {%- endfor %}
2. 在Ansible Playbook中调用模板
- name: 筛选JSON中符合条件的motor条目 hosts: localhost vars: complex_json: cars: - Ford: - vehicle: motor: - diesel: - regular: name: "Regular diesel" specs: law: - id: 1 date: "2008" gas_station: - id: 2 date: "2002" - premium: name: "Premium diesel" specs: law: - id: 3 date: "2005" gas_station: - id: 4 date: "2000" tasks: - name: 渲染模板并输出结果 debug: msg: "{{ lookup('template', 'filter_motor.j2') }}"
运行结果
执行后会输出符合条件的条目:
Premium diesel & 4
扩展说明
- 这个宏会自动遍历所有层级的节点,不管JSON结构如何变化,只要存在
name、id、date键就能匹配 - 如果有多个符合条件的条目,会全部输出
- 可以根据需求修改输出格式,比如改成字典列表、JSON格式等
内容的提问来源于stack exchange,提问作者Costales
相关产品推荐
相关产品推荐

