简体   繁体   English

python JSON解码嵌套列表

[英]python JSON decoding nested list

I am trying to decode JSON into python objects. 我正在尝试将JSON解码为python对象。 Looked at some of the samples/answers here and other website but can't seem to find the answer. 在此处和其他网站上查看了一些示例/答案,但似乎找不到答案。

Here's the code: 这是代码:

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

Here's sample JSON 这是示例JSON

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

I also tried to see if I can re-convert the listOfA back to string and then calling ADecoder. 我还尝试查看是否可以将listOfA重新转换回字符串,然后调用ADecoder。 For example something like this: 例如这样的事情:

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

Firstly this didn't work because Python doesn't know how to convert my object to (JSON) string but even if it did the above that would be terribly inefficient. 首先,这是行不通的,因为Python不知道如何将我的对象转换为(JSON)字符串,但是即使这样做了,效率也非常低下。

Any suggestions on how I could solve the problem? 关于如何解决问题有什么建议吗? Is there a way to inject my ADecoder before Python converts the JSON string to generic objects? 有没有办法在Python将JSON字符串转换为通用对象之前注入ADecoder? Tried looking at the samples, tutorials, etc., can't seem to find this scenario. 试图查看示例,教程等,似乎找不到这种情况。

You must simply rebuild the listOfA as a list comprehension from the list of maps : 您必须简单地从map列表中重建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

Do not try to re-use ADecoder in BDecoder. 不要尝试在BDecoder中重新使用ADecoder。


But this method would not be scalable. 但是这种方法是不可扩展的。 If you want to be able to use deeply nested object, you must refactor your decoders : passing for a json string to an object composed of lists and maps has do be done only once and is as simple as json.load(file) or json.loads(string) . 如果要使用深层嵌套的对象,则必须重构解码器:将json字符串传递给由列表和映射组成的对象仅需执行一次,并且只需json.load(file)json.loads(string)这样简单json.loads(string) But converting those maps to objects has to be done multiple time : this is the part that must be explicitely coded. 但是将这些映射转换为对象必须多次进行:这是必须明确编码的部分。

As your example is simple I just used a static method in class A and B for that : 由于您的示例很简单,因此我仅在类A和B中使用了静态方法:

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'] ])

That way you can easily go one step further: 这样,您可以轻松地进一步:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM