Skip to content
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

Replace NaN/Infinity with null #4908

Merged
merged 1 commit into from May 1, 2018

Conversation

betodealmeida
Copy link
Member

The Python json module will happily encode NaN and ±Infinity:

>>> import json
>>> json.dumps([float('nan'), float('inf'), float('-inf')])
'[NaN, Infinity, -Infinity]'

The problem is that this is not valid JSON, and the browser will choke on the payload when running JSON.parse on it:

> JSON.parse('[NaN, Infinity, -Infinity]');
Uncaught SyntaxError: Unexpected token N in JSON at position 1
    at JSON.parse (<anonymous>)
    at <anonymous>:1:6

To fix this, I used the simplejson module instead, since it provides an argument ignore_nan for converting these values to null as recommended by the JSON spec:

>>> import simplejson as json
>>> json.dumps([float('nan'), float('inf'), float('-inf')], ignore_nan=True)
'[null, null, null]'

@@ -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)
Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Member Author

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-io
Copy link

codecov-io commented Apr 30, 2018

Codecov Report

Merging #4908 into master will decrease coverage by 0.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            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
Impacted Files Coverage Δ
superset/views/core.py 74.68% <100%> (ø) ⬆️
superset/utils.py 87.85% <0%> (-0.22%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d533ce0...1a66e63. Read the comment docs.

@mistercrunch mistercrunch merged commit 9c53323 into apache:master May 1, 2018
@mistercrunch mistercrunch deleted the DPTOOLS-536_use_ignore_nan branch May 1, 2018 20:27
mistercrunch pushed a commit to lyft/incubator-superset that referenced this pull request May 2, 2018
hughhhh pushed a commit to lyft/incubator-superset that referenced this pull request May 16, 2018
michellethomas pushed a commit to michellethomas/panoramix that referenced this pull request May 24, 2018
mistercrunch pushed a commit to lyft/incubator-superset that referenced this pull request May 30, 2018
mistercrunch pushed a commit to lyft/incubator-superset that referenced this pull request May 30, 2018
timifasubaa pushed a commit to timifasubaa/incubator-superset that referenced this pull request May 31, 2018
mistercrunch pushed a commit to lyft/incubator-superset that referenced this pull request Jun 4, 2018
hughhhh pushed a commit to lyft/incubator-superset that referenced this pull request Jun 7, 2018
hughhhh pushed a commit to lyft/incubator-superset that referenced this pull request Jun 7, 2018
hughhhh pushed a commit to lyft/incubator-superset that referenced this pull request Jun 7, 2018
mistercrunch pushed a commit to lyft/incubator-superset that referenced this pull request Jun 7, 2018
hughhhh pushed a commit to lyft/incubator-superset that referenced this pull request Jun 27, 2018
wenchma pushed a commit to wenchma/incubator-superset that referenced this pull request Nov 16, 2018
@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 0.25.0 labels Feb 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 0.25.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants