Отфильтруйте объект по свойству и выберите с помощью ключа в jmespath

Я пытаюсь отфильтровать свойства объекта в jmespath на основе значения вложенного свойства и хочу включить только эти свойства где вложенному свойству присваивается определенное значение.

На основе данных этого примера:

{
  "a": {
    "feature": {
      "enabled": true,
    }
  },
  "b": {
  },
  "c": {
    "feature": {
      "enabled": false
     }
  }
}

Я хочу получить объект со всеми свойствами, в которых эта функция включена.

{
  "a": {
    "feature": {
      "enabled": true,
    }
  }
}

Я решил, что могу использовать этот запрос jmespath для фильтрации объектов, для которых property. enabled установлено значение true. К сожалению, похоже, что это не работает и вместо этого возвращает пустой массив.

*[?feature.enabled==`true`]

*.feature.enabled или *[feature.enabled] возвращают только логические значения без какого-либо контекста.

Даже если *[?feature.enabled==true] будет работать, это будет просто массив значений свойств, но мне также нужны ключи (a и c). Есть ли способ сделать это в jmespath?

Все это часть доступного playbook, поэтому, безусловно, был бы способ добиться выбора другим способом (шаблоны Jinja2 или настраиваемый плагин), но я хотел попробовать jmespath и рассуждал, что он должен быть способен на такую ​​задачу.


person Johannes Müller    schedule 10.01.2017    source источник
comment
Больше, чем запрашивать что-либо, вы хотите удалить определенные ключи на основе вложенных данных. Что-то вроде этого вопроса для Perl. Я тоже хотел бы знать, сможете ли вы сделать это с помощью JMESPath.   -  person techraf    schedule 11.01.2017
comment
См. также: stackoverflow.com/a/55310594/42223   -  person dreftymac    schedule 23.03.2019


Ответы (3)


Извините, но AFAIK это невозможно в собственном JMESPath.
Для этой цели есть специальные встроенные функции в различных инструментах, таких как to_entries в jq.
Для jmespath.py и, следовательно, для Ansible висит запрос на вытягивание для реализации манипуляций с ключами.

Обновление: я сделал исправленную версию фильтра json_query. < br> Дополнительную информацию см. в этом ответе.

person Konstantin Suvorov    schedule 11.01.2017
comment
Спасибо, я следую этому запросу на перенос, и на данный момент я решил эту проблему с помощью цикла jinja2, чтобы выбрать совпадающие элементы словаря и собрать их в новый dict. - person Johannes Müller; 23.01.2017
comment
Похоже, многие онлайн-инструменты просмотра / форматирования json используют jmespath для запросов. Знаете ли вы какой-нибудь хороший инструмент, который вместо этого использует jsonpath? - person MasterJoe; 05.12.2019
comment
не могли бы вы помочь мне в этом связанном вопросе stackoverflow .com / questions / 59206765 /? - person MasterJoe; 06.12.2019

С фильтром dict2items в Ansible 2.5 и новее вы можете сделать это с помощью:

- debug:
    msg: "{{ dict(my_data | dict2items | json_query('[?value.feature.enabled].[key, value]')) }}"

Результат:

"msg": {
    "a": {
        "feature": {
            "enabled": true
        }
    }
}
person techraf    schedule 08.09.2018
comment
не могли бы вы помочь мне в этом связанном вопросе stackoverflow .com / questions / 59206765 /? - person MasterJoe; 06.12.2019

Краткий ответ (TL; DR)

  • На самом деле, да, это возможно только с помощью собственного jmespath
  • Проблема в том, что запросы к исходному набору данных будут чрезвычайно громоздкими, поскольку исходный набор данных плохо нормализован для такого типа универсального запроса jmespath.

Пример

Следующий (слишком длинный) запрос jmespath к исходным данным в OP ...

[
  {
      "item_key":           `a`
      ,"feature_enabled":   @.a.feature.enabled
      ,source_object:       @.a
  }
  ,{
      "item_key":           `b`
      ,"feature_enabled":   @.b.feature.enabled
      ,source_object:       @.b
  }
  ,{
      "item_key":           `c`
      ,"feature_enabled":   @.c.feature.enabled
      ,source_object:       @.c
  }
]|[? feature_enabled == `true`]

... дает следующий результат

[
  {
    "item_key": "a",
    "feature_enabled": true,
    "source_object": {
      "feature": {
        "enabled": true
      }
    }
  }
]

Это идентично или по существу похоже на желаемый результат, но тот факт, что нам пришлось согнуть мозг, чтобы добиться этого, предполагает, что мы пытаемся протолкнуть квадратный колышек через круглое отверстие.

Ловушки

Причина, по которой этот запрос jmespath выглядит таким длинным и громоздким, заключается в том, что сам исходный набор данных плохо нормализован для общего запроса jmespath.

Это потому, что он использует ключи объекта в качестве метода сортировки верхнего уровня, когда было бы достаточно списка с последовательным индексированием.

Всякий раз, когда у вас есть набор данных, который потенциально может содержать произвольное количество значений, почти всегда предпочтительнее использовать последовательность для сопоставления верхнего уровня вместо ключей объектов.

Если вы обнаружите, что можете что-то сделать в jmespath, но вам нужно изменить свой запрос jmespath всякий раз, когда вы добавляете еще одну «запись» в свой «набор записей произвольной (нефиксированной) длины», вы сражаетесь с Jmespath вместо того, чтобы работать с ним. .

Всякий раз, когда вы видите запрос, который кажется "невозможным выполнить" с помощью Jmespath, вы почти наверняка имеете дело со структурой данных, которая использует объекты, для которых последовательности могут быть более подходящими.

Ключи объектов обычно означают фиксированное количество свойств, с которыми jmespath может справиться без проблем.

Даже свойства объекта с произвольной глубиной вложенности вполне приемлемы, если эти свойства объекта не используются в качестве замены последовательному перечислению.

Вещи начинают становиться неудобными только тогда, когда вы обнаруживаете, что вам нужно создавать последовательности-объектов, чтобы обойти объекты-объекты ... что полностью выполнимо в jmespath, но будет болезненно.

Смотрите также

person dreftymac    schedule 23.03.2019
comment
Похоже, многие онлайн-инструменты просмотра / форматирования json используют jmespath для запросов. Знаете ли вы какой-нибудь хороший инструмент, который вместо этого использует jsonpath? - person MasterJoe; 05.12.2019
comment
Например, посмотрите на эту диаграмму: Пример сравнения - person dreftymac; 05.12.2019
comment
Итак, мне интересно, лучше ли использовать какой-нибудь язык программирования вместо любого языка запросов json. JMES выглядит некрасиво. - person MasterJoe; 06.12.2019
comment
не могли бы вы помочь мне в этом связанном вопросе stackoverflow .com / questions / 59206765 /? - person MasterJoe; 06.12.2019