On Aug 9, 2019, at 19:09, Greg Ewing
Andrew Barnert wrote:
No you can’t. Decimal accepts strings that aren’t valid as JSON numbers, like `.3`,
That's not a problem as long as it doesn't serialise them that way, which it wouldn't:
Your suggestion was that we could allow people to serialize whatever they want, and then use the Decimal constructor as a sanity check to make sure it’s actually legal. If someone’s code emits 0.3 and we check it with Decimal instead of with the JSON parser, it gives the wrong answer.
str(Decimal('.3')) '0.3'
or `nan`,
The serialiser could raise an exception in that case.
How? You want to validate by checking if it can be passed to the Decimal constructor, and then add special cases on top of that?
BTW, I just checked what it does with floats:
json.dumps(float('nan')) 'NaN'
So it seems that it currently doesn't care about strict conformance here.
It does care about conformance, but it also cares about interoperability. (This is explained in the docs.) JS implementations before ES5 serialized and parsed NaN, Infinity, and -Infinity, even though the informal spec said they shouldn’t. Lots of other libraries followed suit. (Some also accept or even produce nan, int, -inf, because that’s what most C libraries output—as do Python, Perl, etc.—but many do not.) Modern versions of JS mandate that those values are all emitted as null; some other libraries raise an error; some still use the “legacy” values. Similarly, they vary on what they accept. To deal with all of this, Python’s json module gives you keyword options for both dump and load to select what you want. If you use Decimal to validate the output or a custom emitter, not only it will ignore those flags, and it will also accept things that load wouldn’t accept even if the flag is enabled. I honestly don’t see the point in a sanity check. If we make it possible but not too easy for people to emit whatever raw strings they want into the middle of JSON, they presumably know what they’re doing, and if they really want to produce a non-standard dialect that their code on the other hand can handle, why not just let them? But if we do need such a check, using the Decimal constructor is not a good check. It’s similar to the spec, but not the same, and why validate that someone’s output passes a similar specification instead of the one they’re trying to use? Especially when we already have tested (and configurable) code that exactly parses the actual spec (and common variations on it, depending on the config flags)?