GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-98306: Support JSON encoding of NaNs and infinities as null by mdickinson · Pull Request #115246 · python/cpython

Conversation

@mdickinson

@mdickinson mdickinson commented Feb 10, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

This PR:

  • adds support for allow_nan="as_null" in JSON encoding (json.dump, json.dumps, JSONEncoder.encode). This offers an encoding mode that automatically converts floating-point infinities and NaNs to JSON nulls. This matches the ECMAScript specification for JSON.stringify, so makes interoperability between JavaScript and Python somewhat easier.
  • deprecates use of any other string as a value for allow_nan, to allow space for future expansion of the protocol if necessary

Note that strictly speaking, this is a backwards incompatible change: allow_nan="null" was valid before (since the string "null" is truthy), and this PR changes its meaning. The likelihood of actual breakage from this change seems negligible. Nevertheless, per PEP 387 we would need to request a Steering Council exception before this could be merged.

  • Issue: Proper or custom JSON serialization of non-finite float values #98306

📚 Documentation preview 📚: https://cpython-previews--115246.org.readthedocs.build/

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

a-reich and Disservin reacted with heart emoji
All reactions
  • ❤️ 2 reactions
@mdickinson
pythongh-98306: Support JSON encoding of NaNs and infinities as null
07cc7dc
@bedevere-app bedevere-app Bot added the awaiting core review label Feb 10, 2024
@bedevere-app bedevere-app Bot mentioned this pull request Feb 10, 2024
Proper or custom JSON serialization of non-finite float values #98306
Open
@mdickinson mdickinson mentioned this pull request Feb 10, 2024
Supporting customization of float encoding in JSON #81022
Open
@mdickinson

mdickinson commented Feb 10, 2024

Copy link
Copy Markdown
Member Author

Note: Strictly speaking, this is a backwards incompatible change: allow_nan="null" was valid before (since the string "null" is truthy), and this PR changes its meaning. The likelihood of actual breakage from this change seems likely to be negligible. Nevertheless, per PEP 387 we would need to request a Steering Council exception before this could be merged.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

mdickinson added 4 commits February 10, 2024 15:04
@mdickinson
Add PR number
42e2543
@mdickinson
Spell behavior consistently
a72491c
@mdickinson
Fix inconsistent quote style
b851caf
@mdickinson
Remove extra blank line
35e8d33
@Dzeri96

Dzeri96 commented Mar 3, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

I can't comment on the C implementation as I'm simply unfamiliar with that part of the codebase, but one semantic change I'd suggest is to use "as_null"/"convert_to_null" instead of "null". In my mind, allow_nan="as_null" makes it more obvious as to what the argument does, especially since we're re-using a kwarg with a fairly inflexible name.

Apart from that, I'd really like to avoid using stringified versions of reserved keywords in the code, even if they come from other languages. I'm sure anyone who was unfortunate enough to debug serialization errors can attest to that.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Dzeri96

Dzeri96 commented Mar 3, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

One more thing: Can we type-hint the allow_nan kwarg with a Literal[True, False, "as_null"] ?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

mdickinson added 6 commits May 12, 2024 09:25
@mdickinson
Add a DeprecationWarning for uses of strings other than 'null'
2f7f064
@mdickinson
Refresh news entry
72673dc
@mdickinson
Merge remote-tracking branch 'upstream/main' into enh/json-support-na…
d2cad1d
…n-to-null
@mdickinson
Change 'null' to 'as_null'
79ce75e
@mdickinson
Documentation wording tweaks
ebcd36d
@mdickinson
Grammar and spacing tweaks
acf5642
@mdickinson

mdickinson commented May 12, 2024

Copy link
Copy Markdown
Member Author

In my mind, allow_nan="as_null" makes it more obvious as to what the argument does, especially since we're re-using a kwarg with a fairly inflexible name.

SGTM. I've updated the PR and the description.

One more thing: Can we type-hint the allow_nan kwarg with a Literal[True, False, "as_null"] ?

Python's own std. lib. source doesn't use type hints, as a rule; this would need to be a change in typeshed.

gpshead reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mdickinson
Fix Sphinx role for DeprecationWarning
3062f12
@mdickinson mdickinson mentioned this pull request May 12, 2024
Requesting backwards compatibility exception for change to allow_nan meaning in JSON encoding python/steering-council#244
Closed
@mdickinson

mdickinson commented May 12, 2024

Copy link
Copy Markdown
Member Author

Nevertheless, per PEP 387 we would need to request a Steering Council exception before this could be merged.

python/steering-council#244

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mdickinson mdickinson added the DO-NOT-MERGE label May 12, 2024
@mdickinson

mdickinson commented May 12, 2024 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member Author

Adding DO-NOT-MERGE label, pending response to python/steering-council#244.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@gpshead

gpshead commented May 12, 2024

Copy link
Copy Markdown
Member

API suggestion: Do not use a str literal for the new flag value, use a new singleton json.AS_NULL constant instead.

Use of a str literal on something that also accepts boolean values allows for an anti-pattern of someone making a typo in the value. They may not notice their error as it'd just wind up True. A singleton constant prevents people from coming near a typo prone literal.

Something like this:

class _Singleton:
    def __bool__(self):
        raise RuntimeError(f"Not usable in boolean context.")

AS_NULL = _Singleton()

and just check for that using is within the code on any API where it should be allowed. (or equivalent in a C extension)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@gpshead

gpshead commented May 12, 2024

Copy link
Copy Markdown
Member

Strictly speaking, this is a backwards incompatible change: allow_nan="null" was valid before (since the string "null" is truthy)

Slightly, but not in a way that matters a whole lot. Though if you use AS_NULL instead of a literal as mentioned above, this concern goes away. People will no longer be passing a str and the minimum version supporting this API is clear by the existence of AS_NULL or not. Instead of the code behaving differently based on version when the literal is passed in.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mdickinson

mdickinson commented May 13, 2024

Copy link
Copy Markdown
Member Author

@gpshead I like the suggestion in principle, and it would definitely alleviate the backwards compatibility concerns to the point where an SC exception wouldn't be necessary.

The practical question: how to implement this in a way that the new json.AS_NULL constant is available to the C code? Adding a new type and its instance to _json.c is the obvious way, but it feels like substantial new code for a fairly minor thing. Defining the constant in the Python code and injecting it into the extension module seems possible, but feels fragile to me (I've done something similar in 3rd-party projects, and it generally didn't end well).

I guess there are two, independent, parts to this:

  1. Making the special value a named constant json.AS_NULL and documenting it as such seems like a no-brainer - completely agree with the rationale here. And that would work regardless of what actual concrete type json.AS_NULL happens to have.
  2. Picking a suitable under-the-hood type for json.AS_NULL.

The re module and the re.IGNORE constants and friends seem like a good example of prior art for this problem - I'll take a look at how that works.

gpshead reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@JelleZijlstra

JelleZijlstra commented May 13, 2024

Copy link
Copy Markdown
Member

@mdickinson the re module appears to just use integer flags. You may also want to look at the typing.NoDefault sentinel I added in #116129; I think a very similar implementation would work here.

mdickinson and AlexWaygood reacted with thumbs up emoji
All reactions
  • 👍 2 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mdickinson

mdickinson commented Oct 17, 2024

Copy link
Copy Markdown
Member Author

Closing. I'm not going to have the bandwidth to push this through in the forseeable future. (But if anyone wants to build on what's already here, please feel free to do so.)

gpshead reacted with heart emoji Dzeri96 reacted with eyes emoji
All reactions
  • ❤️ 1 reaction
  • 👀 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mdickinson mdickinson closed this Oct 17, 2024
@coderabbitai coderabbitai Bot mentioned this pull request Jul 29, 2026
Speed up DataFrame conversion utilities opengeos/leafmap#1349
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

awaiting core review DO-NOT-MERGE

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

4 participants

@mdickinson @Dzeri96 @gpshead @JelleZijlstra
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.