-
-
Notifications
You must be signed in to change notification settings - Fork 7k
WIP: Don't convert json to Infinity/NaN #4918
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
cold hard stare |
I'm rather inclined to think that an unhandled exception would be the best possible outcome, with an explicit override available for setting it to |
Please avoid unfounded passive aggressive statement. The behavior is explained in the Python documentation
It's easy to work this around. |
On a side note, I don't see how converting |
@xordoquy You're right, sorry. Fixed |
So which default behavior do we want DRF to have when it encounters what may be a valid Infinity in a float field from the database?
I'm partial to option 3 |
-Use encoder.encode instead of json.dumps. encoder.default can't be used to test floats
This makes the most sense to me, which is a default of option two, but configurable to become option three in @andyneff's list. Also, is there a better way to alter the handling for NaN/infinity? Right now, the PR is duplicating a lot of the |
I would probably prefer an unhandled exception, with the ability for the developer to switch that instead to an explicit override of eg. None or "Infinity" if desired. (Eg. an class attribute on JSONRenderer that can be set.) It's a better situation to loudly fail and force developers to be aware if they've got an edge case that needs dealing with, rather than quietly coercing the value. It is a surprising design choice in the Python JSON lib, but there we are. |
Although practicality beats purity ;) |
I totally agree @rpkilby , I had to duplicate way more code than I'd like to. However because of how the floatstr function is buried, this was the minimum amount of duplication I could get away with (I think, feel free to point me in another direction!) |
Given the amount of overriding required I'd suggest that we'd simply move towards Unless there's a simpler way to achieve this result I don't think it's worth the additional complexity. |
@tomchristie Ok, I can set
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRendererSpecialFloatNull',
'rest_framework.renderers.BrowsableAPIRenderer')
}
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'my_module.MyJSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer')
}
|
I guess making https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/renderers.py#L61 |
Hey Everyone, I'm interested in seeing this feature merged in. What can I do to help get it ready? |
@Michael-J-Ward just yell at me? Lol I haven't forgotten about this, I just keep not being able to find a weekend to work on it. Right now it's still just a POC. We need to
Any assistance would be appreciated |
Problem
By design, json.dumps extends json
However when you tell it to disable allow_nan, it throws an exception instead
Desired result
I choose the Same as Chrome/Firefox route, so,
Importance
It is mentioned in getsentry/sentry#1979, but from my experience I used ajax to GET on a DRF endpoint, and it fails because there was an invalid. this possible outcome or an unhandled exception with allow_nan=False means that a valid infinity in the django database becomes an invalid ajax call.
Solution
After looking at python's json documentation, there is no good/easy way to change exactly how it handles floats to handle exactly what we'd want. "Don't create invalid JSON or throw an exception." Similar SO Most of these involve monkey patching which could easily have unforeseen consequences.
I went ahead and just overrode the iterencode function by combining encoder.py from 2.7, 3.2 and 3.6 to make a version that should support all supported of python without difference.
Other possibility
Instead of returning null every time, it should also be possible to return the string
"Infinity"
instead of trying to return the numberInfinity
. I have no grips with this solution, I just went with the "How does Firefox/Chrome do it"But I believe that it should be ok to say
If you would rather do that, where the quotes will make it just a normal string that will never be reinterpreted as a number again (using the standards).