Python json словарь object_pairs_hook декодирован как None

Я наткнулся на очень удивительное наблюдение при работе со стандартной библиотекой json Python, а точнее при использовании object_pairs_hook оттуда.

Вот мои данные:

items.json:
--
{
    "menuitem": [
      {"value": "New", "onclick": "CreateNewDoc()"},
      {"value": "Open", "onclick": "OpenDoc()"},
      {"value": "Close", "onclick": "CloseDoc()"}
    ]
}
--

И вот мой минимальный рабочий код:

Jupyter QtConsole 4.3.1
Python 3.6.5 |Anaconda, Inc.| (default, Mar 29 2018, 13:32:41) [MSC v.1900 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.

import json

def dummy_hook(input):
    print("INPUT:",input)


filename = r'items.json'
with open(filename, 'r') as f:
    data = json.load(f,object_pairs_hook=dummy_hook)

На удивление (для меня) результат таков:

INPUT: [('value', 'New'), ('onclick', 'CreateNewDoc()')]
INPUT: [('value', 'Open'), ('onclick', 'OpenDoc()')]
INPUT: [('value', 'Close'), ('onclick', 'CloseDoc()')]
INPUT: [('menuitem', [None, None, None])]

В частности, вы поймете, что три словаря с парами «значение» / «onclick» были декодированы в None. Это проблема для меня, так как я надеялся проделать с ними какие-то дополнительные операции.

Вопросы: этого следует ожидать? Я что-то здесь неправильно делаю?

Обновлено: Итак, изменив функцию перехвата на:

def dummy_hook(input):
    print("INPUT:",input)
    return 7

Действительно меняет результат печати на:

INPUT: [('value', 'New'), ('onclick', 'CreateNewDoc()')]
INPUT: [('value', 'Open'), ('onclick', 'OpenDoc()')]
INPUT: [('value', 'Close'), ('onclick', 'CloseDoc()')]
INPUT: [('menuitem', [7,7,7])]

Я до сих пор не понимаю, как добавление оператора return меняет результат декодирования. Но да, в принципе, это решает проблему.

Нужно что-то вернуть от dummy_hook()

Maurice Meyer 10.12.2018 12:40
dummy_hook возвращает None, да, это ожидаемое поведение.
juanpa.arrivillaga 10.12.2018 12:42

Вопрос не столько в том, что возвращает dummy_hook, поскольку это, вероятно, ясно из определения функции, сколько в том, почему список словарей из исходного файла json декодируется в список None и зачем добавлять оператор return в dummy_hook меняет это поведение.

Simon Righley 10.12.2018 13:08

Я не уверен, что вы не понимаете. Результат функции используется как значение декодированного объекта. Ваша первая функция всегда возвращала None, а вторая всегда возвращает 7 .... эти объекты будут декодированы как None и 7`.

juanpa.arrivillaga 10.12.2018 18:14
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
4
522
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Думаю, ваша функция dummy_hook должна возвращать значение. В вашем случае, возможно, такой же ввод.

object_pairs_hook is an optional function that will be called with the result of any object literal decoded with an ordered list of pairs. The return value of object_pairs_hook will be used instead of the dict. This feature can be used to implement custom decoders that rely on the order that the key and value pairs are decoded (for example, collections.OrderedDict() will remember the order of insertion). If object_hook is also defined, the object_pairs_hook takes priority.

от: https://docs.python.org/3.6/library/json.html#json.load

Я до сих пор не понимаю, почему, но да, это решило эту проблему.

Simon Righley 10.12.2018 13:10

Другие вопросы по теме