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/