From 700fc7d928b7a625b04e6865b3eb282043e90f7d Mon Sep 17 00:00:00 2001 From: David Lord Date: Mon, 15 Jan 2024 07:47:13 -0800 Subject: [PATCH] untag without object_hook --- CHANGES.rst | 3 +++ src/flask/json/tag.py | 14 +++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 9f79995b46..27c04f7f3e 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ Unreleased - Correct type for ``path`` argument to ``send_file``. :issue:`5230` - Fix a typo in an error message for the ``flask run --key`` option. :pr:`5344` +- Session data is untagged without relying on the built-in ``json.loads`` + ``object_hook``. This allows other JSON providers that don't implement that. + :issue:`5381` Version 3.0.0 diff --git a/src/flask/json/tag.py b/src/flask/json/tag.py index 91cc4412d6..069739f264 100644 --- a/src/flask/json/tag.py +++ b/src/flask/json/tag.py @@ -305,10 +305,22 @@ def untag(self, value: dict[str, t.Any]) -> t.Any: return self.tags[key].to_python(value[key]) + def _untag_scan(self, value: t.Any) -> t.Any: + if isinstance(value, dict): + # untag each item recursively + value = {k: self._untag_scan(v) for k, v in value.items()} + # untag the dict itself + value = self.untag(value) + elif isinstance(value, list): + # untag each item recursively + value = [self._untag_scan(item) for item in value] + + return value + def dumps(self, value: t.Any) -> str: """Tag the value and dump it to a compact JSON string.""" return dumps(self.tag(value), separators=(",", ":")) def loads(self, value: str) -> t.Any: """Load data from a JSON string and deserialized any tagged objects.""" - return loads(value, object_hook=self.untag) + return self._untag_scan(loads(value))