Странное поведение при разборе JSON диктует объекты с помощью object_hook - PullRequest
3 голосов
/ 04 февраля 2011

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

import json

class Obj:
    '''
    classdocs
    '''

    def __init__(self,s,hello="Hello world!"):
        '''
        Constructor
        '''
        self.s = s
        self.hello = hello
    def __repr__(self):
        return '<MyObj(%s,%s)>' % (self.s, self.hello)

def objToJSON(obj):
    return obj.__dict__

def jSONToObj(json):
    print(json)
    return Obj(**json)

if __name__ == '__main__':
    str = json.dumps(Obj("Hello","World"), default=objToJSON, sort_keys=True)
    print(str)
    print(json.loads(str,object_hook=jSONToObj))
    str = json.dumps(Obj("Text",{"a":"aaaa","b":"BBBBB","C":"ccccc"}), default=objToJSON, sort_keys=True)
    print(str)
    print(json.loads(str,object_hook=jSONToObj))

Выход которого:

{"hello": "World", "s": "Hello"}
{'s': 'Hello', 'hello': 'World'}
<MyObj(Hello,World)>
{"hello": {"C": "ccccc", "a": "aaaa", "b": "BBBBB"}, "s": "Text"}
{'a': 'aaaa', 'C': 'ccccc', 'b': 'BBBBB'}
Traceback (most recent call last):
  File "C:\Users\dimo414\src\test.py", line 27, in <module>
    print(json.loads(str,object_hook=jSONToObj))
  File "C:\Python31\lib\json\__init__.py", line 318, in loads
    return cls(**kw).decode(s)
  File "C:\Python31\lib\json\decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "C:\Python31\lib\json\decoder.py", line 355, in raw_decode
    obj, end = self.scan_once(s, idx)
  File "C:\Users\dimo414\src\test.py", line 22, in jSONToObj
    return Obj(**json)
TypeError: __init__() got an unexpected keyword argument 'a'

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

1 Ответ

3 голосов
/ 04 февраля 2011

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

Из документов:

object_hook - дополнительная функция это будет вызвано с результатом любой объект буквального декодирования (dict). Возвращаемое значение object_hook будет использоваться вместо слова. это функция может быть использована для реализации пользовательские декодеры (например, класс JSON-RPC намекая).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...