我正在研究一个小问题,将一些JSON(我不能改变格式,它不是我创建的服务)反序列化为Python对象。我已经设法使用lambda进行转换,但我现在想使用object_hook,看看是否可以使用json.loads
方法进行转换。然而,这就是我现在失败的地方,我想知道是否有人能指出我正确的方向。
这是我目前的代码:
import json
class Light:
def __init__(self, id, name):
self.id = id
self.name = name
response = '{"1": {"name": "bedroom"}, "2": {"name": "kitchen"}}'
def object_decoder(obj):
return Light(......)
print json.loads(response, object_hook=object_decoder)
正如您所看到的,response
是一个包含两个键的文档,名为1和2.如果我能够以json.loads
将返回的方式使代码工作,那将是很好的两个Light对象,但此刻,我被卡住了,我不知道如何迭代响应以使其工作。
答案 0 :(得分:5)
object_hook
对您没有帮助,因为您在json字符串中的不同级别上有id
和name
:
object_hook,如果指定,将使用every的结果调用 解码JSON对象并使用其返回值代替 给出了词典。
让我们看看为什么object_hook
无济于事。如果您打印的是object_decoder
函数的对象,您会看到它从深处开始,如下所示:
{u'name': u'bedroom'}
{u'name': u'kitchen'}
{u'1': None, u'2': None}
None
这意味着您无法加入object_decoder
次调用以生成Light
个实例。
如何使用自定义JSONDecoder类:
import json
class Light:
def __init__(self, id, name):
self.id = id
self.name = name
response = '{"1": {"name": "bedroom"}, "2": {"name": "kitchen"}}'
class Decoder(json.JSONDecoder):
def decode(self, s):
obj = super(Decoder, self).decode(s)
return [Light(id=k, name=v['name']) for k, v in obj.iteritems()]
lights = json.loads(response, cls=Decoder)
print lights # prints [<__main__.Light instance at 0x9c3b50c>, <__main__.Light instance at 0x9c3b56c>]
print [light.__dict__ for light in lights] # prints [{'id': u'1', 'name': u'bedroom'}, {'id': u'2', 'name': u'kitchen'}]
这实际上与制作json.loads()
然后在实例化后实现类相同。
答案 1 :(得分:1)
如果您能够更改字符串的格式,建议您使用jsonpickle。我已经成功完成了这类事情。