将对象列表编码为JSON对象

时间:2013-10-16 19:21:38

标签: python json matlab

我想扩展标准库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兼容的复数对象?

1 个答案:

答案 0 :(得分:1)

从简要介绍simplejson源代码开始,似乎没有简单的方法以自下而上的方式对JSON进行编码。我建议两种可能的解决方案:

  • 使用不可迭代或非列表对象(即json模块未解析的内容)来包含复数列表,以便它由default()编码并且不是json.JSONEncoder
  • 在编码其余部分之前对复数列表进行编码,这样json编码器就不必在子对象之前处理父对象的编码。