2

我正在处理一个小问题,将一些 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 对象的方式工作,那就太好了,但是目前,我被卡住了,而且我不知道如何迭代响应来完成这项工作。

4

2 回答 2

6

object_hookid对您没有帮助,因为您name在 json 字符串中具有不同的级别:

object_hook,如果指定,将调用每个 JSON 对象的解码结果,其返回值将用于代替给定的 dict。

让我们看看为什么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()然后实例化类相同。

于 2013-09-02T20:06:40.780 回答
1

如果您能够更改字符串的格式,我建议您使用jsonpickle。我已经建立了它非常适合这种事情。

于 2013-09-02T20:10:17.313 回答