JMESPath 或 Ansible 扁平化字典
JMESPath or Ansible flatten dictionaries
我想像这样转换输入:
{
"cluster1": {
"services": {
"service1": {
"name": "foo",
"version": 1.0
},
"service2": {
"name": "bar",
"version": 2.0
}
}
},
"cluster2": {
"services": {
"service3": {
"name": "test",
"version": 3.0
},
"service4": {
"name": "s4",
"version": 4.0
}
}
},
"cluster3": {
"services": {
"service5": {
"name": "s5",
"version": 5.0
}
}
},
"clusterx": {
"name": "value"
}
}
或这个(哪个无关紧要):
[
{
"key": "cluster1",
"value": {
"services": {
"service1": {
"name": "foo",
"version": 1.0
},
"service2": {
"name": "bar",
"version": 2.0
}
}
}
},
{
"key": "cluster2",
"value": {
"services": {
"service3": {
"name": "test",
"version": 3.0
},
"service4": {
"name": "s4",
"version": 4.0
}
}
}
},
{
"key": "cluster3",
"value": {
"services": {
"service5": {
"name": "s5",
"version": 5.0
}
}
}
},
{
"key": "clusterx",
"value": {
"name": "value"
}
}
]
进入这个:
[
{ "name": "service1", "value": {
"name": "foo",
"version": 1
},
{ "name": "service2", "value": {
"name": "bar",
"version": 2
},
{ "name": "service3", "value": {
"name": "test",
"version": 3
},
{ "name": "service4", "value": {
"name": "s4",
"version": 4
},
{ "name": "service5", "value": {
"name": "s5",
"version": 5
}
]
基本上我希望看到所有扁平化服务的列表。
可以用 JMESPath 做到这一点吗?
到目前为止,我对第二种输入类型的了解是:[?value.services].value.services
将我的输入转换为:
[
{
"service1": {
"name": "foo",
"version": 1
},
"service2": {
"name": "bar",
"version": 2
}
},
{
"service3": {
"name": "test",
"version": 3
},
"service4": {
"name": "s4",
"version": 4
}
},
{
"service5": {
"name": "s5",
"version": 5
}
}
]
所以我想我需要另一个级别的扁平化,但我不确定该怎么做。
顺便说一句,我正在使用 Ansible,其中 json_query 与 JMESPath 非常相似。
所以如果我们能用 Ansible 实现这个 / json_query,那也是完美的。
在 Ansible 中,我尝试了类似这样的东西,它几乎已经存在,但不完全是:
all_services: |
{{ input | dict2items | json_query('[?value.services].value.services') }}
我们先组合一个扁平化的服务字典。例如
- set_fact:
all_services_dict: "{{ all_services_dict|default({})|combine(item) }}"
loop: "{{ input|json_query('*.services') }}"
- debug:
var: all_services_dict
给予
"all_services_dict": {
"service1": {
"name": "foo",
"version": 1.0
},
"service2": {
"name": "bar",
"version": 2.0
},
"service3": {
"name": "test",
"version": 3.0
},
"service4": {
"name": "s4",
"version": 4.0
},
"service5": {
"name": "s5",
"version": 5.0
}
}
然后将服务串联成一个列表。例如
- set_fact:
all_services_list: "{{ all_services_list|default([]) +
[{'name': item.key,
'value': item.value}] }}"
loop: "{{ all_services_dict|dict2items }}"
- debug:
var: all_services_list
给予
"all_services_list": [
{
"name": "service1",
"value": {
"name": "foo",
"version": 1.0
}
},
{
"name": "service2",
"value": {
"name": "bar",
"version": 2.0
}
},
{
"name": "service3",
"value": {
"name": "test",
"version": 3.0
}
},
{
"name": "service4",
"value": {
"name": "s4",
"version": 4.0
}
},
{
"name": "service5",
"value": {
"name": "s5",
"version": 5.0
}
}
]
我想像这样转换输入:
{
"cluster1": {
"services": {
"service1": {
"name": "foo",
"version": 1.0
},
"service2": {
"name": "bar",
"version": 2.0
}
}
},
"cluster2": {
"services": {
"service3": {
"name": "test",
"version": 3.0
},
"service4": {
"name": "s4",
"version": 4.0
}
}
},
"cluster3": {
"services": {
"service5": {
"name": "s5",
"version": 5.0
}
}
},
"clusterx": {
"name": "value"
}
}
或这个(哪个无关紧要):
[
{
"key": "cluster1",
"value": {
"services": {
"service1": {
"name": "foo",
"version": 1.0
},
"service2": {
"name": "bar",
"version": 2.0
}
}
}
},
{
"key": "cluster2",
"value": {
"services": {
"service3": {
"name": "test",
"version": 3.0
},
"service4": {
"name": "s4",
"version": 4.0
}
}
}
},
{
"key": "cluster3",
"value": {
"services": {
"service5": {
"name": "s5",
"version": 5.0
}
}
}
},
{
"key": "clusterx",
"value": {
"name": "value"
}
}
]
进入这个:
[
{ "name": "service1", "value": {
"name": "foo",
"version": 1
},
{ "name": "service2", "value": {
"name": "bar",
"version": 2
},
{ "name": "service3", "value": {
"name": "test",
"version": 3
},
{ "name": "service4", "value": {
"name": "s4",
"version": 4
},
{ "name": "service5", "value": {
"name": "s5",
"version": 5
}
]
基本上我希望看到所有扁平化服务的列表。
可以用 JMESPath 做到这一点吗?
到目前为止,我对第二种输入类型的了解是:[?value.services].value.services
将我的输入转换为:
[
{
"service1": {
"name": "foo",
"version": 1
},
"service2": {
"name": "bar",
"version": 2
}
},
{
"service3": {
"name": "test",
"version": 3
},
"service4": {
"name": "s4",
"version": 4
}
},
{
"service5": {
"name": "s5",
"version": 5
}
}
]
所以我想我需要另一个级别的扁平化,但我不确定该怎么做。
顺便说一句,我正在使用 Ansible,其中 json_query 与 JMESPath 非常相似。 所以如果我们能用 Ansible 实现这个 / json_query,那也是完美的。
在 Ansible 中,我尝试了类似这样的东西,它几乎已经存在,但不完全是:
all_services: |
{{ input | dict2items | json_query('[?value.services].value.services') }}
我们先组合一个扁平化的服务字典。例如
- set_fact:
all_services_dict: "{{ all_services_dict|default({})|combine(item) }}"
loop: "{{ input|json_query('*.services') }}"
- debug:
var: all_services_dict
给予
"all_services_dict": {
"service1": {
"name": "foo",
"version": 1.0
},
"service2": {
"name": "bar",
"version": 2.0
},
"service3": {
"name": "test",
"version": 3.0
},
"service4": {
"name": "s4",
"version": 4.0
},
"service5": {
"name": "s5",
"version": 5.0
}
}
然后将服务串联成一个列表。例如
- set_fact:
all_services_list: "{{ all_services_list|default([]) +
[{'name': item.key,
'value': item.value}] }}"
loop: "{{ all_services_dict|dict2items }}"
- debug:
var: all_services_list
给予
"all_services_list": [
{
"name": "service1",
"value": {
"name": "foo",
"version": 1.0
}
},
{
"name": "service2",
"value": {
"name": "bar",
"version": 2.0
}
},
{
"name": "service3",
"value": {
"name": "test",
"version": 3.0
}
},
{
"name": "service4",
"value": {
"name": "s4",
"version": 4.0
}
},
{
"name": "service5",
"value": {
"name": "s5",
"version": 5.0
}
}
]