Python和JSON:使用object_hook进行多个不同类的类型提示
在使用 Python 2.6 的 json 模块时,我在把一个函数传给 object_hook 时遇到了一些意想不到的问题。我想把一个 JSON 对象转换成我代码中定义的一个类。这个类需要传入另一个类的实例作为参数。大概是这样的:
class OuterClass:
def __init__(self, arg, *InnerClass_instances):
self.arg = arg
self.class2 = InnerClass_instances
class InnerClass:
def __init__(self, name, value):
self.name = name
self.value = value
我觉得,如果要创建一个包含 OuterClass 实例所有信息的 JSON 对象,就必须把每个 InnerClass 实例的信息也包含在内。所以,我想写两个函数来解析 JSON 对象,一个处理 OuterClass,另一个处理 InnerClass,并让创建 OuterClass 的函数调用创建 InnerClass 实例的函数。大概是这样的:
def create_InnerClass(dct):
if '__InnerClass__' in dct:
name = dct['name']
value = dct['value']
return InnerClass(name, value)
def create_OuterClass(dct):
if '__OuterClass__' in dct:
arg = dct['arg']
InnerClass_instances = [create_InnerClass(dct2) \
for dct2 in dct['InnerClass_instances']]
return OuterClass(arg, *InnerClass_intances)
我原以为这样做是可以的:
s = #triple quotes omitted for syntax highlighting reasons
{
"__OuterClass__": true,
"arg": 4,
"InnerClass_instances":
[
{"__InnerClass__": true, "name": "Joe", "value": 12},
{"__InnerClass__": true, "name": "Jimmy", "value":7}
]
}
outerClass = json.loads(s, object_hook = creat_OuterClass)
然而,像上面那样调用 json.loads 时却返回了这个错误:
if '__InnerClass__' in dct:
TypeError: argument of type 'NoneType' is not iterable
不过,简单地调用 json.loads(s),然后再用 json.dumps(outerClass) 就完全没问题。所以,看起来是我处理 object_hook 参数的方式出了问题,导致定义 InnerClass 实例的字典变成了 NoneType 对象。我是不是对 object_hook 函数在解析 JSON 对象时的用法理解错了?
有没有办法在一个 JSON 对象中为多种类进行类型提示?到目前为止,我读到的内容都没有说明这是否可行。
1 个回答
并不是每次调用 create_OuterClass
时,__OuterClass__
都会出现在 dct
这个字典里。所以,你的 create_OuterClass
函数需要处理这种情况。默认情况下,它会返回 dct
:
def create_OuterClass(dct):
# print('create_OuterClass: {0}'.format(dct))
if '__OuterClass__' in dct:
arg = dct['arg']
InnerClass_instances = [create_InnerClass(dct2)
for dct2 in dct['InnerClass_instances']]
return OuterClass(arg, *InnerClass_instances)
return dct
如果你加上上面的打印语句,你会得到
create_OuterClass: {u'__InnerClass__': True, u'name': u'Joe', u'value': 12}
create_OuterClass: {u'__InnerClass__': True, u'name': u'Jimmy', u'value': 7}
create_OuterClass: {u'__OuterClass__': True, u'InnerClass_instances': [{u'__InnerClass__': True, u'name': u'Joe', u'value': 12}, {u'__InnerClass__': True, u'name': u'Jimmy', u'value': 7}], u'arg': 4}
这段内容展示了 json.loads
是如何使用 object_hook
这个回调函数的。
它首先会用内部的字典调用这个函数,之后才会用外部的字典。