将JSON反序列化为Object

Eri*_*agt 1 python json deserialization

我正在研究一个微不足道的问题,将一些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)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,这response是一个带有两个键的文档,名为1和2.如果我可以使代码工作的方式json.loads将返回两个Light对象,那将是很好的,但此刻,我卡住了,我不知道如何迭代响应使这项工作.

ale*_*cxe 5

object_hook不会帮你,因为你有idname不同层次上的JSON字符串:

如果指定了object_hook,则将调用每个JSON对象的结果,并使用其返回值代替给定的dict.

让我们看看为什么object_hook不会有所帮助.如果您打印要进入该object_decoder功能的对象,您将看到它从深处上升,如下所示:

{u'name': u'bedroom'}
{u'name': u'kitchen'}
{u'1': None, u'2': None}
None
Run Code Online (Sandbox Code Playgroud)

这意味着您无法加入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'}]
Run Code Online (Sandbox Code Playgroud)

这实际上json.loads()与之后制作然后实例化类相同.