2011-02-04 11 views
3

私はexploring the json libraryでした。オブジェクトをJSONデータに変換しようとしています。私は、この例のコードを実行している問題に実行した:JSONを構文解析してobject_hookを使用してオブジェクトに奇妙な動作をさせる

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に渡されたデータがあると思われます内部辞書であり、完全辞書ではない。何故ですか?

答えて

3

関数jSONToObjを使用してオブジェクトを再構築するように指定したので、デシリアライザはすべてのdictがオブジェクトであるとみなし、それらのデシリアライザをコールしようとします。ドキュメントから

object_hookは 任意のオブジェクトリテラルデコード(辞書)の結果を用いて呼び出されるオプション機能 あります。 object_hookの戻り値は、dictの代わりに になります。この 機能は、 カスタムデコーダ(JSON-RPCクラス ヒントなど)を実装するために使用できます。

loadsが再帰的に動作し、最下位層から開始するため、内側のdictが最初にデシリアライズされます。オブジェクトをデシリアライズする前に、引数を逆シリアル化する必要があります。

+0

デシリアライザは、すべてのdictsがオブジェクトであると仮定しているのはなぜですか?なぜオブジェクトには辞書が含まれていないのですか? – dimo414

+0

ディクテーションには型の注釈がないため、json関数は決して伝えることができません。デシリアライザ関数 'jSONToObj'は、dictとdictでないものを自分自身で決定し、オブジェクトやdictを適切に返さなければなりません。 –

+0

ちょうどトップレベルのオブジェクトだけが必要な場合は、いつものようにJSONからデータをデシリアライズして、手動で結果のdict /リストをオブジェクトに変換することを検討してください。 –