diff --git a/docs/config.rst b/docs/config.rst index c2958bf715..2600da34a9 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -315,6 +315,14 @@ The following configuration values are used internally by Flask: Default: ``True`` +.. py:data:: JSON_STRICT + + Raise an error when encountering values that cannot be serialized in a + strictly JSON compliant manner (such as ``NaN`` and ``Infinity``), + rather than encoding them as such. + + Default: ``False`` + .. py:data:: JSONIFY_PRETTYPRINT_REGULAR ``jsonify`` responses will be output with newlines, spaces, and indentation diff --git a/flask/app.py b/flask/app.py index 87c5900348..fb93af785f 100644 --- a/flask/app.py +++ b/flask/app.py @@ -304,6 +304,7 @@ class Flask(_PackageBoundObject): 'PREFERRED_URL_SCHEME': 'http', 'JSON_AS_ASCII': True, 'JSON_SORT_KEYS': True, + 'JSON_STRICT': False, 'JSONIFY_PRETTYPRINT_REGULAR': False, 'JSONIFY_MIMETYPE': 'application/json', 'TEMPLATES_AUTO_RELOAD': None, diff --git a/flask/json/__init__.py b/flask/json/__init__.py index fbe6b92f0a..33ee84a8f7 100644 --- a/flask/json/__init__.py +++ b/flask/json/__init__.py @@ -102,6 +102,9 @@ def _dump_arg_defaults(kwargs): if not current_app.config['JSON_AS_ASCII']: kwargs.setdefault('ensure_ascii', False) + if current_app.config['JSON_STRICT']: + kwargs.setdefault('allow_nan', False) + kwargs.setdefault('sort_keys', current_app.config['JSON_SORT_KEYS']) else: kwargs.setdefault('sort_keys', True) @@ -173,6 +176,10 @@ def dumps(obj, **kwargs): default which coerce into unicode strings automatically. That behavior by default is controlled by the ``JSON_AS_ASCII`` configuration variable and can be overridden by the simplejson ``ensure_ascii`` parameter. + + If the ``JSON_STRICT`` config parameter is set to True, this function will + raise a :exc:`ValueError` if it encounters values that cannot be represented in + a JSON specification compliant manner. """ _dump_arg_defaults(kwargs) encoding = kwargs.pop('encoding', None) diff --git a/tests/test_basic.py b/tests/test_basic.py index c0168ae3bd..ffd2e36bac 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -1298,6 +1298,14 @@ def test_jsonify_prettyprint(app, req_ctx): assert rv.data == pretty_response +@pytest.mark.parametrize('test_value', [float('nan'), float('Infinity')]) +def test_json_strict(app, req_ctx, test_value): + app.config.update({'JSON_STRICT': True}) + + with pytest.raises(ValueError) as e: + flask.jsonify(test_value) + assert 'not JSON compliant' in str(e.value) + def test_jsonify_mimetype(app, req_ctx): app.config.update({"JSONIFY_MIMETYPE": 'application/vnd.api+json'}) msg = { diff --git a/tests/test_helpers.py b/tests/test_helpers.py index b3535b2831..dea7a55998 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -155,7 +155,7 @@ def test_json_dump_to_file(self, app, app_ctx): rv = flask.json.load(out) assert rv == test_data - @pytest.mark.parametrize('test_value', [0, -1, 1, 23, 3.14, 's', "longer string", True, False, None]) + @pytest.mark.parametrize('test_value', [0, -1, 1, 23, 3.14, float('Infinity'), 's', "longer string", True, False, None]) def test_jsonify_basic_types(self, test_value, app, client): """Test jsonify with basic types."""