So -
I think that is clear by now that in your case you really are not loosing
any precision with these numbers.

However, as noted, there is no way to customize Python JSON encoder
to encode an arbitrary decimal number in JSON, even though the standard does
allow it, and Python supports then via decimal.Decimal.

Short of a long term solution, like a __json__ protocol, or at least special
support in Python json module for objects of type "numbers.Number",
the only way to go, is, as you are asking, being able to insert "raw
strings into json".

Given that this feature can be needed now, I fashioned a JsonEncoder class
that is able to
do that - by annotating decimal.Decimal instances on encoding, and making
raw string replacements before returning the final encoded value.

This recipe is ready to be used at
https://gist.github.com/jsbueno/5f5d200fd77dd1233c3063ad6ecb2eee
(Note that I don't consider this approach fit for the stdlib due to having
to rely on regular expressions,
and having to create a copy of the whole encoded json-body - if there is
demand,
I might package it though).


Please enjoy.

  js
 -><-

On Thu, 8 Aug 2019 at 07:27, Richard Musil <risa20...@gmail.com> 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 [31]: float(0.6441726684570313)
> Out[31]: 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.
>
> I noticed that `simplejson` provides an explicit option for its standard
> serializing function, called `use_decimal`, which basically solves my
> problem., but I would just like to use the standard module, I guess.
>
> So the question is, if something like `use_decimal` has been considered
> for the standard module, and if yes, why it was not implemented, or the
> other option could be to support "raw output" in the serializer, e.g.
> something like:
> class DecimalEncoder(json.JSONEncoder):
>     def raw(self, o):
>         if isinstance(o, decimal.Decimal):
>             return str(o) # <- This is a raw representation of the object
>         return super.raw(o)
> Where the returning values will be directly passed to the output stream
> without adding any additional characters. Then I could write my own Decimal
> serializer with few lines of code above.
>
> If anyone would want to know, why the last digit matters (or why I cannot
> double quote the floats), it is because the file has a secure hash attached
> and this basically breaks it.
> _______________________________________________
> 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/WT6Z6YJDEZXKQ6OQLGAPB3OZ4OHCTPDU/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
_______________________________________________
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/TY6YCFTH5IBRSVOQQX5NDOBEWJSPKAFI/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to