我无法理解json.loads()中的object_hook功能是如何工作的。我在这里发现了一个类似的问题object_hook does not address the full json,但我试图按照我所了解的内容进行操作,但它仍然不适用于我。我已经收集到以某种方式递归调用object_hook函数,但我无法理解如何使用它从json字符串构造复杂的对象层次结构。请看下面的JSON字符串,类和object_hook功能:json模块中的object_hook似乎并不像我期望的那样工作
import json
from pprint import pprint
jstr = '{"person":{ "name": "John Doe", "age": "46", \
"address": {"street": "4 Yawkey Way", "city": "Boston", "state": "MA"} } }'
class Address:
def __init__(self, street=None, city=None, state=None):
self.street = street
self.city = city
self.state = state
class Person:
def __init__(self, name=None, age=None, address=None):
self.name = name
self.age = int(age)
self.address = Address(**address)
def as_person(jdict):
if u'person' in jdict:
print('person found')
person = jdict[u'person']
return Person(name=person[u'name'], age=person[u'age'],
address=person[u'address'])
else:
return('person not found')
return jdict
(我定义与关键字ARGS类提供的默认值,这样的JSON不需要包含所有要素,我还是可以保证的属性存在于。类的实例我也将最终关联方法与类,但想从JSON数据填充实例)
如果我运行:
>>> p = as_person(json.loads(jstr))
我得到了我希望,即:
person found
和P成为一个Person对象,即:
>>> pprint(p.__dict__)
{'address': <__main__.Address instance at 0x0615F3C8>,
'age': 46,
'name': u'John Doe'}
>>> pprint(p.address.__dict__)
{'city': u'Boston', 'state': u'MA', 'street': u'4 Yawkey Way'}
然而,如果不是,我尝试使用:
>>> p = json.loads(jstr, object_hook=as_person)
我得到:
person found
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
File "C:\Program Files (x86)\Python27\lib\json\__init__.py", line 339, in loads
return cls(encoding=encoding, **kw).decode(s)
File "C:\Program Files (x86)\Python27\lib\json\decoder.py", line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "C:\Program Files (x86)\Python27\lib\json\decoder.py", line 382, in
raw_decode
obj, end = self.scan_once(s, idx)
File "<interactive input>", line 5, in as_person
TypeError: string indices must be integers, not unicode
我不知道为什么会发生这种情况,并怀疑有关object_hook机制如何工作的细节我错过了。
在试图以纳入上述问题,这是该object_hook评估从下往上每个嵌套的字典(?和横向将其替换)的概念,我也试过:
def as_person2(jdict):
if u'person' in jdict:
print('person found')
person = jdict[u'person']
return Person2(name=person[u'name'], age=person[u'age'], address=person[u'address'])
elif u'address' in jdict:
print('address found')
return Address(jdict[u'address'])
else:
return('person not found')
return jdict
>>> json.loads(jstr, object_hook=as_person2)
address found
person found
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
File "C:\Program Files (x86)\Python27\lib\json\__init__.py", line 339, in loads
return cls(encoding=encoding, **kw).decode(s)
File "C:\Program Files (x86)\Python27\lib\json\decoder.py", line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "C:\Program Files (x86)\Python27\lib\json\decoder.py", line 382, in raw_decode
obj, end = self.scan_once(s, idx)
File "<interactive input>", line 5, in as_person2
AttributeError: Address instance has no attribute '__getitem__'
所以显然,object_hook函数的正确形式正在逃避我。
有人可以详细解释object_hook机制如何工作,以及如何从底层向上递归构造生成的对象树,为什么我的代码无法按预期工作,并修复我的示例或提供一个使用object_hook函数来构建一个复杂的类,因为你只能得到一个object_hook函数?
您确认了“人”的内容吗? –
我意识到我忘了上面发布我的Person2类;我更改了Person类中的地址分配,只是说 self.address =地址 –
@ScottHunter:如果你的意思是p,是的;它是一个Person实例: <__ main __。0x0615F148>个人实例>。 (其他调用从来没有那么远。) –