我想扩展标准库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 编码器不必在子对象之前处理对父对象的编码。