我無法理解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>個人實例>。 (其他調用從來沒有那麼遠。) –