Richard Musil wrote:
I have found myself in an awkward situation with current (Python 3.7) JSON module. Basically it boils down to how it handles floats. I had been hit on this particular case:
In : float(0.6441726684570313) Out: 0.6441726684570312
but I guess it really does not matter.
What matters is that I did not find a way how to fix it with the standard `json` module. I have the JSON file generated by another program (C++ code, which uses nlohmann/json library), which serializes one of the floats to the value above. Then when reading this JSON file in my Python code, I can get either decimal.Decimal object (when specifying `parse_float=decimal.Decimal`) or float. If I use the latter the least significant digit is lost in deserialization.
If I use Decimal, the value is preserved, but there seems to be no way to "serialize it back". Writing a custom serializer:
class DecimalEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, decimal.Decimal): return str(o) # <- This becomes quoted in the serialized output return super.default(o)
seems to only allow returning "string" value, but then serializes it as a string! I.e. with the double quotes. What seems to be missing is an ability to return a "raw textual representation" of the serialized object which will not get mangled further by the `json` module.
You have overwritten the wrong method:
$ cat demo.py import io import json import decimal
class DecimalEncoder(json.JSONEncoder): def encode(self, o): if isinstance(o, decimal.Decimal): return str(o) return super().encode(o)
input = "0.6441726684570313" obj = json.loads(input, parse_float=decimal.Decimal) output = json.dumps(obj, cls=DecimalEncoder) assert input == output $ python3 demo.py $