Объединить значение атрибута с помощью json_query в доступном

Я хочу объединить два атрибута в одну строку, разделенную разделителем, с помощью json_query в доступе
Примеры данных

{
  "locations": [
    {"name": "Seattle", "state": "WA"},
    {"name": "New York", "state": "NY"},
    {"name": "Bellevue", "state": "WA"},
    {"name": "Olympia", "state": "WA"}
  ]
}

Как показано в приведенном выше наборе данных, я пытаюсь отфильтровать состояние WA, и выполненный вывод:

[
    "Seattle-WA",
    "Bellevue-WA",
    "Olympia-WA"
]

Что я пробовал на данный момент:

    - debug:
        msg: "{{ chart_list.HELM_CHARTS | json_query(\"[?state == 'WA'].{name:name,state:state}\") }}"
Output:
[
  {
    "name": "Seattle",
    "state": "WA"
  },
  {
    "name": "Bellevue",
    "state": "WA"
  },
  {
    "name": "Olympia",
    "state": "WA"
  }
]

Обновлено: мне удалось получить ожидаемый результат методом проб и ошибок, и вот мои выводы:

[?state == 'WA'].[join('-',[name,state])][]
Output:
[
  "Seattle-WA",
  "Bellevue-WA",
  "Olympia-WA"
]

Также, если вводимые вами данные находятся в формате Unicode, я предлагаю вам добавить to_json | from_json выражений, как указано ниже:

        selected_cities: "{{ test.locations| to_json | from_json | json_query(\"[?state == 'WA'].[join('-',[name,state])][]\") }}"

Использование приведенного выше выражения устранит ошибку Unicode при использовании значений или в любых условиях. Посетите сайт JMESPath для получения более подробной информации о json_query, это действительно помогло решить проблему.


person Snkini    schedule 03.03.2021    source источник
comment
Я вижу бесчисленное множество вопросов о том, как подчиниться json_query воле вопрошающего, но я не понимаю одержимости этим. В Jinja2 есть for петли с удобным selectattr фильтром, и они отлично работают.   -  person mdaniel    schedule 04.03.2021
comment
Привет, @mdaniel, причина, по которой я хотел, чтобы это было в json_query, заключалась в том, чтобы быстро получить доступ к необходимым данным из огромного набора данных в зависимости от условия. Я согласен, что циклы будут работать, но я немного знаком с этим плагином :-)   -  person Snkini    schedule 04.03.2021


Ответы (2)


Например

    - debug:
        msg: "{{ locations|
                 json_query('[?state == `WA`].[name,state]')|
                 map('join', '-')|list }}"

дает

  msg:
  - Seattle-WA
  - Bellevue-WA
  - Olympia-WA

Тот же результат дает приведенная ниже задача с использованием только фильтров Jinja2.

    - debug:
        msg: "{{ _names|zip(_states)|map('join', '-')|list }}"
      vars:
        _locations: "{{ locations|selectattr('state', 'eq', 'WA')|list }}"
        _names: "{{ _locations|map(attribute='name')|list }}"
        _states: "{{ _locations|map(attribute='state')|list }}"

Проблема с json_query (исправлена ​​в 2.10 и более поздних версиях)

Есть JMESPath join. к несчастью

    - debug:
        msg: "{{ locations|
                 json_query('[].join(`-`, [name,state])') }}"

терпит неудачу

msg: | - JMESPathError в плагине фильтра json_query: в функции join () недопустимый тип для значения: Сиэтл, ожидалось одно из: ['array-string'], получено: AnsibleUnicode

to_json | from_json временное решение

Цитата из json_query: добавьте примеры для start_with и содержит # 72821

структуру данных, возвращаемую из регистровых переменных, необходимо проанализировать с помощью to_json | from_json, чтобы получить правильный результат. Исправления: ansible-collections / community.general # 320

    - debug:
        msg: "{{ locations|to_json|from_json|
                 json_query('[].join(`-`, [name,state])') }}"

дает

  msg:
  - Seattle-WA
  - New York-NY
  - Bellevue-WA
  - Olympia-WA
person Vladimir Botka    schedule 04.03.2021
comment
(Есть соединение JMESPath. Я также хотел бы узнать, как его использовать.) ›Желание исполнено. - person β.εηοιτ.βε; 04.03.2021
comment
К сожалению, у меня это не работает. (доступный 2.9.6, python3-jmespath 0.9.4-2). Можно ли выложить рабочие версии? - person Vladimir Botka; 04.03.2021
comment
Ой? Попробую вернуться к 2.9 из моей последней и посмотреть, что за этим стоит - person β.εηοιτ.βε; 04.03.2021
comment
Похоже, это проблема to_json | from_json, которая была устранена на 2.10, но влияет на 2.9 - person β.εηοιτ.βε; 04.03.2021

Просто ради чистого JMESPath способа сделать это, поскольку ваше решение проб и ошибок по-прежнему имеет ненужный дополнительный уровень сложности.

Когда ты делаешь

[?state == 'WA'].[join('-', [name, state])][]

Вы создаете массив [join('-', [name, state])], а затем без причины [] сглаживаете его.

Вы можете просто перейти к решению с более коротким подходом:

[?state == `WA`].join(`-`, [name, state])

Также помните, что вы можете преодолеть кавычки в кавычках (простые или двойные) для запросов JMESPath, используя:

  1. Многострочная строка YAML: Как разбить строку в YAML на несколько строк?

  2. # P7 #
    # P8 #
    # P9 #

В итоге вы получите (см. Примечание ниже, если вы используете версию Ansible ‹2.10):

- debug:
    msg: >-
      {{ test.locations 
           | json_query('[?state == `WA`].join(`-`, [name, state])') }}

Обратите внимание: как указано @Vladimir Botka в версиях до 2.10, вы будет затронута эта проблема: https://github.com/ansible/ansible/issues/27299#issuecomment-331068246, заставляя вас добавить | to_json | from_json фильтр в список.


Учитывая пьесу:

- hosts: all
  gather_facts: yes

  tasks:
    - debug:
        msg: >-
          {{ test.locations 
              | json_query('[?state == `WA`].join(`-`, [name, state])') 
          }}
      vars:
        test:
          locations:
            - name: Seattle
              state: WA
            - name: New York
              state: NY
            - name: Bellevue
              state: WA
            - name: Olympia
              state: WA

Это дает:

[
    "Seattle-WA",
    "Bellevue-WA",
    "Olympia-WA"
]
person β.εηοιτ.βε    schedule 04.03.2021