From a841cfabb58d3c1ac1d11b09353f458e759a63c2 Mon Sep 17 00:00:00 2001 From: olliemath Date: Sat, 20 Nov 2021 14:05:57 +0000 Subject: [PATCH] Only use a custom JSONDecoder if needed The default JSONDecoder adds no extra functionality to `json.loads`, but using a custom class in the function call you off of an optimized fast path in pypy (it adds some overhead in cpython, but I think it's minimal). This change sticks with the default loading behaviour unless the user has specifically opted in to customising it. Co-authored-by: David Lord --- CHANGES.rst | 3 +++ src/flask/json/__init__.py | 12 +++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 05609229..1af03f26 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -12,6 +12,9 @@ Unreleased - Fix type annotation for ``errorhandler`` decorator. :issue:`4295` - Revert a change to the CLI that caused it to hide ``ImportError`` tracebacks when importing the application. :issue:`4307` +- ``app.json_encoder`` and ``json_decoder`` are only passed to + ``dumps`` and ``loads`` if they have custom behavior. This improves + performance, mainly on PyPy. :issue:`4349` Version 2.0.2 diff --git a/src/flask/json/__init__.py b/src/flask/json/__init__.py index 10d5123a..ccb9efb1 100644 --- a/src/flask/json/__init__.py +++ b/src/flask/json/__init__.py @@ -81,6 +81,11 @@ def _dump_arg_defaults( if bp is not None and bp.json_encoder is not None: cls = bp.json_encoder + # Only set a custom encoder if it has custom behavior. This is + # faster on PyPy. + if cls is not _json.JSONEncoder: + kwargs.setdefault("cls", cls) + kwargs.setdefault("cls", cls) kwargs.setdefault("ensure_ascii", app.config["JSON_AS_ASCII"]) kwargs.setdefault("sort_keys", app.config["JSON_SORT_KEYS"]) @@ -102,9 +107,10 @@ def _load_arg_defaults( if bp is not None and bp.json_decoder is not None: cls = bp.json_decoder - kwargs.setdefault("cls", cls) - else: - kwargs.setdefault("cls", JSONDecoder) + # Only set a custom decoder if it has custom behavior. This is + # faster on PyPy. + if cls not in {JSONDecoder, _json.JSONDecoder}: + kwargs.setdefault("cls", cls) def dumps(obj: t.Any, app: t.Optional["Flask"] = None, **kwargs: t.Any) -> str: