python JSON解码嵌套列表

时间:2015-08-05 15:18:31

标签: python json

我正在尝试将JSON解码为python对象。看了一些这里的样本/答案和其他网站,但似乎无法找到答案。

以下是代码:

import json
class A:
    def __init__ (self, n, a):
        self.n = n
        self.a = a

class B:
    def __init__ (self, b, listOfA):
        self.b = b
        self.listOfA = []
        for a in listOfA:
            self.listOfA.append(a)

class ADecoder(json.JSONDecoder):
    def decode (self, json_string):
        default_obj = super(A, self).decode(json_string)
        a_obj = A(default_obj['n'], default_obj['a'])
        return a_obj

class BDecoder(json.JSONDecoder):
    def decode (self, json_string):
        default_obj = super(BDecoder, self).decode(json_string)
        #The problem with the code above is that here listOfA is a list of
        #generic python objects.
        b_obj = B(default_obj['b'], [default_obj['listOfA']])
        return b_obj

以下是JSON示例

{
    "b": "b", 
    "listOfA": [
        {
            "a": "a1", 
            "n": "n1"
        }, 
        {
            "a": "a2", 
            "n": "n2"
        }
    ], 
}

我还试着看看是否可以将listOfA重新转换回字符串,然后再调用ADecoder。例如:

aDecoder = ADecoder()
b_obj = B(default_obj['b'], [aDecoder.decode(x.__str__()) for x in default_obj['servers']])

首先这不起作用,因为Python不知道如何将我的对象转换为(JSON)字符串,但即使它执行上述操作也会非常低效。

有关如何解决问题的任何建议?有没有办法在Python将JSON字符串转换为通用对象之前注入我的ADecoder?尝试查看示例,教程等,似乎无法找到这种情况。

1 个答案:

答案 0 :(得分:2)

您必须从地图列表中重建listOfA作为列表理解:

class BDecoder(json.JSONDecoder):
    def decode (self, json_string):
        default_obj = super(BDecoder, self).decode(json_string)
        b_obj = B(default_obj['b'], [A(x['n'], x['a']) for x in default_obj['listOfA'] ] )
        return b_obj

请勿尝试在BDecoder中重复使用ADecoder。

但这种方法不具备可扩展性。如果您希望能够使用深层嵌套对象,则必须重构解码器:将json字符串传递给由列表和映射组成的对象只需执行一次,就像json.load(file)或{{一样简单1}}。但是,将这些地图转换为对象必须多次完成:这是必须明确编码的部分。

由于你的例子很简单,我只是在A和B类中使用静态方法:

json.loads(string)

这样你就可以更进一步:

class A:
    def __init__ (self, n, a):
        self.n = n
        self.a = a
    @staticmethod
    def decode(jsonMap):
        return A(jsonMap['n'], jsonMap['a'])

class B:
    def __init__ (self, b, listOfA):
        self.b = b
        self.listOfA = list(listOfA)
    @staticmethod
    def decode(jsonMap):
        return B(jsonMap['b'], [ A.decode(x) for x in jsonMap['listOfA'] ])