Глубоко получить элемент из JSON со значением по умолчанию в Python

1

У меня есть произвольно вложенный json. Я хочу получить некоторое значение, которое имеет несколько ключей, и не имеет гарантии, что любой из ключей присутствует.

Так, например, я могу захотеть получить value = json_dict['a'][1]['q']['e'] но в любой момент я могу получить KeyError, если a, q или e не существует или ошибка индекса за пределами границ, если json_dict['a'] имеет менее двух элементов. Если какое-либо из этих условий истинно, я хочу, чтобы value было value по умолчанию, есть ли способ сделать это, это одна или две строки без необходимости вставлять кучу операторов if или get вызовы?

  • 0
    Похоже, довольно легко написать функцию. Дайте ему диктовку, список ключей, переберите список по мере того, как вы индексируете поддикты, и при необходимости отлавливаете ошибки. По крайней мере, вы должны быть в состоянии начать с этим.
  • 0
    Что означает «Если какое-либо из этих условий два»? Означает ли это, что по крайней мере два «ключа» отсутствуют?
Показать ещё 3 комментария
Теги:

1 ответ

3
Лучший ответ

Вы можете поместить простую чистую версию python вместе:

def get_path(data, path, default=None):
    try:
        for item in path:
            data = data[item]
        return data
    except (KeyError, TypeError, IndexError):
        return default


nice_data = {'a': [None, {'q': {'e': 'Hello!'}}]}
bad_data = {'a': 6}
path = ['a', 1, 'q', 'e']

print('Good', get_path(nice_data, path))   # Hello!
print('Bad', get_path(bad_data, path))     # None

Не супер фантазия, но она работает.


Если вы хотите сделать что-то в одной меньшей строке, с немного большей мощностью, мы можем использовать что-то вроде ObjectPath (https://pypi.org/project/objectpath/):

from objectpath import Tree

def get_object_path(data, path, default=None):
    try:
        return Tree(data).execute(path)
    except (KeyError, TypeError, IndexError):
        return default


path = '$.a[1].q.e'
print('Good', get_object_path(nice_data, path))
print('Bad', get_object_path(bad_data, path))

Нам еще предстоит обработать свою собственную обработку ошибок, и она будет намного медленнее, но она может поддерживать всевозможные причудливые запросы (из документов):

In weather readings find cities where temperature is higher than 25°C and the sky is clear.
$..*[@..temp > 25 and @.clouds.all is 0].name 
  • 0
    IndexError вы не должны кроме IndexError s?
  • 0
    Да. Вы определенно должны. Я исправлю пример. Благодарю.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню