Skip to main content
 首页 » 编程设计

python之将对象列表编码为 JSON 对象

2025年05月04日10zhengyun_ustc

我想扩展标准库 Python JSON encoder将复数列表编码为由 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 编码器就不必在子对象之前处理对父对象的编码。