将对象列表编码为 JSON 对象



我想扩展标准库Python JSON编码器,将复数列表编码为由JSONLAB(MATLAB的非官方JSON工具箱)正确解析的表示形式。 简而言之,单个 Python 复数(x + yj)应编码为 JSON 复数对象,

{"_ArrayType_": "double",
 "_ArraySize_": [1, 1],
 "_ArrayIsComplex_": 1,
 "_ArrayData_": [x, y]}

以及复数列表[(x1 + y1j), (x2+y2j), (x3+y3j)]应成为单个 JSON 复数对象,

{"_ArrayType_": "double",
 "_ArraySize_": [1, 3],
 "_ArrayIsComplex_": 1,
 "_ArrayData_": [[x1, y1], [x2, y2], [x3, y3]]}

我已经能够正确编码单个复数,如下所示:

class ComplexEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, complex):
            return {"_ArrayType_": "double", "_ArraySize_": [1, 1],
                    "_ArrayIsComplex_": 1, "_ArrayData_": [obj.real, obj.imag]}
        return json.JSONEncoder.default(self, obj)

我尝试了对复数列表的情况进行直接扩展,但它并不完全有效:

class ComplexEncoder(json.JSONEncoder):
    def default(self, obj):
        # if obj is a list containing at least one complex number
        if isinstance(obj, list) and sum(map(lambda x: isinstance(x, complex),
                                             obj)):
            data = [[elem.real, elem.imag] for elem in obj]
            return {"_ArrayType_": "double", "_ArraySize_": [1, len(obj)],
                    "_ArrayIsComplex_": 1, "_ArrayData_": data}
        elif isinstance(obj, complex):
            return {"_ArrayType_": "double", "_ArraySize_": [1, 1],
                    "_ArrayIsComplex_": 1, "_ArrayData_": [obj.real, obj.imag]}
        return json.JSONEncoder.default(self, obj)

如果此类用于解析复数的 Python 列表,则结果是包含 1x1 JSON 复数对象的 JSON 列表,而不是单个 JSON 复数对象。 Python 对象似乎是"自下而上"而不是"自上而下"解析的,在注意到它们在列表中之前,将复数转换为 1x1 JSON 复数对象。

如何最好地将复数列表编码为与JSONLAB兼容的复数对象?

通过简要浏览simplejson源代码,除了自下而上之外,似乎没有简单的方法可以以任何方式对 JSON 进行编码。我建议两种可能的解决方案:

  • 使用不可迭代或非列表对象(即json模块不解析的东西)来包含复数列表,以便它由 default() 而不是 json.JSONEncoder 编码。
  • 在对其余数字进行编码之前对复数列表进行编码,以便 json 编码器不必在子对象之前处理对父对象的编码。

最新更新