2
votes

I would like to extend the standard library Python JSON encoder to encode lists of complex numbers into a representation correctly parsed by JSONLAB, the unofficial JSON toolbox for MATLAB. Briefly, a single Python complex number (x + yj) should be encoded as a JSON complex number object,

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

and a list of complex numbers [(x1 + y1j), (x2+y2j), (x3+y3j)] should also become a single JSON complex number object,

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

I have been able to correctly encode a single complex number, like so:

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)

I tried a straightforward extension to the case of a complex number list, but it does not quite work:

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)

If this class is used to parse a Python list of complex numbers, the result is a JSON list of 1x1 JSON complex number objects, rather than a single JSON complex number object. It seems that the Python object is parsed "bottom-up," rather than "top-down," with the complex numbers converted into 1x1 JSON complex number objects before it is noticed that they're in a list.

How best to encode lists of complex numbers into complex number objects compatible with JSONLAB?

1

1 Answers

1
votes

From taking a brief look through the simplejson source code, there seems to be no easy way to encode the JSON in any way other than bottom up. I'd suggest two possible solutions:

  • Using a non-iterable or non-list object (i.e. something that the json module doesn't parse) to contain the list of complex numbers, so that it will be encoded by default() and not json.JSONEncoder.
  • Encode the lists of complex numbers before encoding the rest, so that the json encoder doesn't' have to deal with encoding parent objects before child objects.