Skip to content

Add JSON_STRICT config option - #2832

Closed
abought wants to merge 1 commit into
pallets:masterfrom
abought:feature/jsonify-strict-mode
Closed

Add JSON_STRICT config option#2832
abought wants to merge 1 commit into
pallets:masterfrom
abought:feature/jsonify-strict-mode

Conversation

@abought

@abought abought commented Jun 16, 2018

Copy link
Copy Markdown

Summary

Provide a new config option to control how JSON is serialized. This would prevent situations where Flask returns a response that is not actually JSON specification compliant.

This proposal is an opt-in mechanism. For backwards compatibility, it is disabled by default.

Purpose

The default Python JSON serializer is not strictly RFC-compliant. In particular, it outputs
Infinity and NaN values.

This means that by default, JSON APIs written in Flask may produce output that cannot be parsed by the browser, especially when dealing with numerical data.

Enabling the newly provided JSON_STRICT option would treat this scenario as an application error server-side and raise an exception. It would be up to the application developer to identify their preferred handling of such values.

Changes and scope

This adds a new JSON_STRICT config option, adding to the existing config flags that also control serialization.

The default value is chosen to leave existing applications unaffected. If JSON_STRICT is True, the application will raise an error in situations where it previously would have produced invalid JSON.

Previous discussion

This pitfall has been noted previously elsewhere. Others have expressed an interest in a simple, explicit configurable error option, but I am not aware of any previous pull requests that implemented the idea.

Particularly due to backwards compatibility concerns, the Python standard library has rejected previous suggestions to change the default json module behavior:
https://bugs.python.org/issue26105

Evaluation of alternatives

Libraries such as simplejson provide an ECMA-262 compliant ignore_nan option, in which out-of-range values are serialized as null.

However, this option is not supported by the Python standard library, and in practice the best choice of replacement value may be somewhat application specific.

Allow flask to raise an error rather than return
data that is not JSON specification compliant.

Useful for edge cases such as `NaN` or `Infinity`, for which
the replacement value is application-dependent.
@davidism

Copy link
Copy Markdown
Member

We already support simplejson if it's installed. This seems like a good case for a custom serializer rather than a configuration option.

@abought

abought commented Jun 16, 2018

Copy link
Copy Markdown
Author

Thanks for your comment. If you prefer a refined or alternate approach, I would be happy to iterate on this and follow up...?

The key idea is that by default, a web application framework is producing JSON output that cannot be parsed by web browsers. I think there is a niche within flask core for a simple, obvious, and configurable way to warn about this.

The current mechanisms in flask are powerful, but only after the fact. Before a developer can write a custom serializer, first they must know the issue is occurring. The current default behavior is hard to track down, because it involves special values like infinity and the application claims to be acting normally.

Per your other note: although flask uses simplejson if installed, it does not expose or enable the relevant underlying options. (Mainly because functions such as jsonify treat kwargs as data, rather than options)

@davidism

davidism commented Jan 6, 2019

Copy link
Copy Markdown
Member

I'd prefer not to add another config option. You can accomplish the same thing with:

from flask.json import JSONEncoder

class StrictEncoder(JSONEncoder):
    def __init__(self, *args, allow_nan=False, **kwargs):
        kwargs["allow_nan"] = allow_nan
        super().__init__(*args, **kwargs)

app.json_encoder = StrictEncoder

@davidism davidism closed this Jan 6, 2019
@davidism

davidism commented Jan 7, 2019

Copy link
Copy Markdown
Member

Basically, if your app happens to produce these, and you don't want it to, then you should be sanitizing your data before serialization anyway. Either you do allow_nan=False and present a mysterious 500 error to your user, or you ensure your data is correct before sending it.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Nov 14, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants