-
Notifications
You must be signed in to change notification settings - Fork 15k
Replace NaN/Infinity with null #4908
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
@@ -2435,7 +2436,7 @@ def sql_json(self): | |||
|
|||
resp = json_success(json.dumps( | |||
{'query': query.to_dict()}, default=utils.json_int_dttm_ser, | |||
allow_nan=False), status=202) | |||
ignore_nan=True), status=202) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a little bit scary as it was set to False explicitly in the past, probably for a reason. I'm guessing the default is True
and someone set it to False
for some specific reason. We should do a bit of git forensics to understand how it came to be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. This is super confusing naming. Just to clarify:
allow_nan=False
: will raise an exception if the data has NaN/Infinity;ignore_nan=True
: will encode NaN/Infinity as nulls.
I'm assuming what happened was that someone had an async query returning NaN/Infinity, and since the stdlib json
module does not have the ignore_nan
argument the easiest way is to work around is to raise an exception here. It took me a while to learn that simplejson
had this option.
I looked at the blame and couldn't find any info about this. The reason I changed this as well was to make it consistent with the sync call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Digging in a bit more, I found the first commit where this was introduced by some guy called @mistercrunch: 38b8db805 :-P
Initially both sync and async responses used allow_nan=False
. Eventually it got dropped from the sync response in 269f55c29 when the pessimistic encoder was introduced. The pessimistic encoder was not added to the async response because the commit is trying to fix gigantic HTML error messages, but IMHO it should've been added as well.
The problem is that the pessimistic encoder doesn't handle NaN
and ±Infinity
because they're floats, so the JSON encoder never calls the default
method on them.
I think the change above is safe — it will return some result instead of failing with a ValueError
exception. But I think the best approach would be using a more robust serialization to send data to the browser, like BSON.
Codecov Report
@@ Coverage Diff @@
## master #4908 +/- ##
==========================================
- Coverage 77.13% 77.12% -0.02%
==========================================
Files 44 44
Lines 8542 8542
==========================================
- Hits 6589 6588 -1
- Misses 1953 1954 +1
Continue to review full report at Codecov.
|
(cherry picked from commit 9c53323)
(cherry picked from commit 9c53323)
(cherry picked from commit 9c53323)
(cherry picked from commit 9c53323)
(cherry picked from commit 9c53323)
(cherry picked from commit 9c53323)
(cherry picked from commit 9c53323)
(cherry picked from commit 9c53323)
(cherry picked from commit 9c53323)
(cherry picked from commit 9c53323)
The Python
json
module will happily encodeNaN
and±Infinity
:The problem is that this is not valid JSON, and the browser will choke on the payload when running
JSON.parse
on it:To fix this, I used the
simplejson
module instead, since it provides an argumentignore_nan
for converting these values tonull
as recommended by the JSON spec: