Friday, 14 October 2022

Deserialize json string containing arbitrary-precision float numbers, and serialize it back

Python has no built-in arbitrary-precision floats. Here is an example:

>>> float(4.4257052820783003)
4.4257052820783

So it doesn't matter what you use, you can't have a float object with arbitrary precision.

Let's say I have a JSON string (json_string = '{"abc": 4.4257052820783003}') containing an arbitrary-precision float. If I load that string, Python will cut the number:

>>> dct = json.loads(json_string)
>>> dct
{'abc': 4.4257052820783}

I managed to avoid this loss of info by using decimal.Decimal:

>>> dct = json.loads(json_string, parse_float=Decimal)
>>> dct
{'abc': Decimal('4.4257052820783003')}

Now, I would like to serialize this dct object to the original JSON formatted string. json.dumps(dct) clearly does not work (because objects of type Decimal are not JSON serializable). I tried to subclass json.JSONEncoder and redefine its default method:

class MyJSONEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, Decimal):
            return str(o)
        return super().default(o)

But this is clearly creating a string instead of a number:

>>> MyJSONEncoder().encode(dct)
'{"abc": "4.4257052820783003"}'

How can I serialize a Decimal object to a JSON number (real) instead of a JSON string? In other words, I want the encode operation to return the original json_string string. Ideally without using external packages (but solutions using external packages are still welcome).

This question is of course very related but I can't find an answer there: Python JSON serialize a Decimal object.



from Deserialize json string containing arbitrary-precision float numbers, and serialize it back

No comments:

Post a Comment