OK, going back to your original question:

On Thu, 8 Aug 2019 at 11:24, Richard Musil <risa20...@gmail.com> wrote:

> 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.

The thing is, if you were allowed to insert arbitrary text (your "raw
textual representation") into a JSON stream, the result wouldn't be
JSON any more.

If you want to dump user-defined types in a JSON stream, you need to
do so by defining a structure (defined in terms of the fundamental
types that JSON supports) that you can serialise to the JSON stream.
That's why the encoder default() method returns an object, not a
string.

So, for example, you could serialise and deserialise decimals as follows:

>>> import json
>>> import decimal
>>>
>>> class DecimalEncoder(json.JSONEncoder):
...     def default(self, o):
...         if isinstance(o, decimal.Decimal):
...             # Return a JSON "object" with 2 attributes:
type="Decimal", value=the string representation of the value
...             return {"type": "Decimal", "value": str(o)}
...         return super.default(o)
...
>>>
>>> def as_decimal(dct):
...     if dct.get("type") == "Decimal" and "value" in dct:
...         return decimal.Decimal(dct["value"])
...
>>> x = json.dumps([12, 34.56, decimal.Decimal("789.876")], cls=DecimalEncoder)
>>> x
'[12, 34.56, {"type": "Decimal", "value": "789.876"}]'
>>> json.loads(x, object_hook=as_decimal)
[12, 34.56, Decimal('789.876')]

What you *can't* do is change how the fundamental types are
represented, or have a specialised deserialiser for anything that's
not a JSON "object" type. The point of the customisation facility is
to transport non-JSON types via a JSON stream, retaining type
information. Not to modify how the JSON stream is represented as a
string.

So no, I don't think there's any fundamental asymmetry here, nor do I
think there's anything particular missing[1]. I just think you've
misunderstood the purpose behind the customisation facilities in the
json module.

Paul

[1] Assuming you accept that controlling the exact serialisation of
fundamental JSON types is a non-goal, which you claim you do accept,
even though your use case seems based on the idea that you want to be
able to serialise floating point numbers in a consistent format across
different JSON libraries...
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/KR3EO7LTTN4BPLGC5WKEGMDSEAW4SRSF/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to