Словари JMESPath или Ansible flatten - PullRequest
1 голос
/ 29 мая 2020

Я хотел бы преобразовать ввод следующим образом:

{
    "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
    }
  }
]

Итак, я думаю, мне нужен другой уровень сглаживания, но я не уверен, как это сделать.

I Кстати, я использую Ansible, где json_query очень похож на JMESPath. Так что, если мы сможем добиться этого с помощью Ansible / json_query, это тоже отлично.

В Ansible Я пробовал что-то вроде этого, что почти есть, но не совсем:

all_services: |
  {{ input | dict2items | json_query('[?value.services].value.services') }}

1 Ответ

0 голосов
/ 29 мая 2020

Давайте сначала объединим плоский словарь услуг. Например,

    - 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
            }
        }
    ]
...