如何在 Jinja 中过滤字典?
How to filter dictionaries in Jinja?
我有一个包的字典,包名是 key,一些细节的字典是 value:
{
"php7.1-readline": {
"latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"origins": [
"ppa.launchpad.net"
],
"version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1",
"www": "http://www.php.net/"
},
"php7.1-xml": {
"latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"origins": [
"ppa.launchpad.net"
],
"version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1",
"www": "http://www.php.net/"
},
"plymouth": {
"version": "0.8.8-0ubuntu17.1"
},
....
}
我想将上面的内容缩减为只有包的字典,这些包的值具有 latest
-属性。
似乎 json_query
是要使用的过滤器,但我无法弄清楚语法。那里的例子似乎都在 lists 字典上运行,而不是 dictionaries of same...
例如,如果我"pipe"上面的字典变成json_query('*.latest')
,我得到实际最新版本的列表:
[
"7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"7.1.6-2~ubuntu14.04.1+deb.sury.org+1"
]
如何获取整个字典元素?
有希望吗?
您不能仅使用 Jinja 过滤器执行此转换(我 认为 ),但您也可以通过应用一些 Ansible 逻辑来实现。以下剧本使用 with_dict
循环遍历字典中的项目,并根据匹配项构建新字典:
- hosts: localhost
vars:
packages: {
"php7.1-readline": {
"latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"origins": [
"ppa.launchpad.net"
],
"version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1",
"www": "http://www.php.net/"
},
"php7.1-xml": {
"latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"origins": [
"ppa.launchpad.net"
],
"version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1",
"www": "http://www.php.net/"
},
"plymouth": {
"version": "0.8.8-0ubuntu17.1"
}
}
tasks:
- set_fact:
new_packages: >
{{ new_packages|default({})|
combine({item.key: item.value}) }}
with_dict: "{{ packages }}"
when: "{{ item.value.latest is defined }}"
- debug:
var: new_packages
你对 link 这个问题 是正确的。
开箱即用 json_query 没有同时操作键和值的选项(从 Ansible 2.4.0 开始)。
这里是补丁 json_query.py,支持类似 jq 的 to_entries
/from_entries
函数。
您可以将其放入剧本附近的 ./filter_plugins
并进行以下查询:
- debug:
msg: "{{ pkg | json_query('to_entries(@) | [?value.latest].{key:key, value:value.latest} | from_entries(@)')}}"
得到这个结果:
"msg": {
"php7.1-readline": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"php7.1-xml": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1"
}
一有空我就把PR给ansible
使用 dict2items
过滤器 added in December 2017,可以使用本机功能:
- debug:
msg: "{{ dict(pkg | dict2items | json_query('[?value.latest].[key, value.latest]')) }}"
结果:
"msg": {
"php7.1-readline": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"php7.1-xml": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1"
}
我有一个包的字典,包名是 key,一些细节的字典是 value:
{
"php7.1-readline": {
"latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"origins": [
"ppa.launchpad.net"
],
"version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1",
"www": "http://www.php.net/"
},
"php7.1-xml": {
"latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"origins": [
"ppa.launchpad.net"
],
"version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1",
"www": "http://www.php.net/"
},
"plymouth": {
"version": "0.8.8-0ubuntu17.1"
},
....
}
我想将上面的内容缩减为只有包的字典,这些包的值具有 latest
-属性。
似乎 json_query
是要使用的过滤器,但我无法弄清楚语法。那里的例子似乎都在 lists 字典上运行,而不是 dictionaries of same...
例如,如果我"pipe"上面的字典变成json_query('*.latest')
,我得到实际最新版本的列表:
[
"7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"7.1.6-2~ubuntu14.04.1+deb.sury.org+1"
]
如何获取整个字典元素?
有希望吗?
您不能仅使用 Jinja 过滤器执行此转换(我 认为 ),但您也可以通过应用一些 Ansible 逻辑来实现。以下剧本使用 with_dict
循环遍历字典中的项目,并根据匹配项构建新字典:
- hosts: localhost
vars:
packages: {
"php7.1-readline": {
"latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"origins": [
"ppa.launchpad.net"
],
"version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1",
"www": "http://www.php.net/"
},
"php7.1-xml": {
"latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"origins": [
"ppa.launchpad.net"
],
"version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1",
"www": "http://www.php.net/"
},
"plymouth": {
"version": "0.8.8-0ubuntu17.1"
}
}
tasks:
- set_fact:
new_packages: >
{{ new_packages|default({})|
combine({item.key: item.value}) }}
with_dict: "{{ packages }}"
when: "{{ item.value.latest is defined }}"
- debug:
var: new_packages
你对 link 这个问题
开箱即用 json_query 没有同时操作键和值的选项(从 Ansible 2.4.0 开始)。
这里是补丁 json_query.py,支持类似 jq 的 to_entries
/from_entries
函数。
您可以将其放入剧本附近的 ./filter_plugins
并进行以下查询:
- debug:
msg: "{{ pkg | json_query('to_entries(@) | [?value.latest].{key:key, value:value.latest} | from_entries(@)')}}"
得到这个结果:
"msg": {
"php7.1-readline": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"php7.1-xml": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1"
}
一有空我就把PR给ansible
使用 dict2items
过滤器 added in December 2017,可以使用本机功能:
- debug:
msg: "{{ dict(pkg | dict2items | json_query('[?value.latest].[key, value.latest]')) }}"
结果:
"msg": {
"php7.1-readline": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
"php7.1-xml": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1"
}