From 05e06d0e3aa17d2d5cc3d155e914bd41d6bcc09c Mon Sep 17 00:00:00 2001 From: dot Date: Fri, 9 Oct 2026 19:43:53 +0900 Subject: [PATCH] Skip overridden items for empty dictionaries in JSON encoding Split the Python 3.14-compatible empty native dictionary fast path from #8954. Extend the existing JSON snippet with root, nested, sorting, and nonempty subclass regression coverage. Assisted-by: OpenAI Codex:model identifier unavailable --- crates/stdlib/src/json.rs | 4 ++++ extra_tests/snippets/stdlib_json.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/crates/stdlib/src/json.rs b/crates/stdlib/src/json.rs index e553dbb652b..1716d673f15 100644 --- a/crates/stdlib/src/json.rs +++ b/crates/stdlib/src/json.rs @@ -1160,6 +1160,10 @@ mod _json { out: &mut Wtf8Buf, vm: &VirtualMachine, ) -> PyResult<()> { + if dict.is_empty() { + out.push_str("{}"); + return Ok(()); + } let mut items = self.dict_items(obj, dict, vm)?; if items.is_empty() { out.push_str("{}"); diff --git a/extra_tests/snippets/stdlib_json.py b/extra_tests/snippets/stdlib_json.py index e55382c8223..8366a19cd66 100644 --- a/extra_tests/snippets/stdlib_json.py +++ b/extra_tests/snippets/stdlib_json.py @@ -67,6 +67,24 @@ def json_load(obj): assert "{}" == json_dump({}) assert round_trip_test({"a": "b"}) + +class EmptyDictWithItems(dict): + def items(self): + raise AssertionError("items() must not be called for an empty dictionary") + + +for sort_keys in (False, True): + assert json.dumps(EmptyDictWithItems(), sort_keys=sort_keys) == "{}" + assert json.dumps([EmptyDictWithItems()], sort_keys=sort_keys) == "[{}]" + + +class NonemptyDictWithItems(dict): + def items(self): + return [("replacement", 2)] + + +assert json.dumps(NonemptyDictWithItems(original=1)) == '{"replacement": 2}' + # should reject non-str keys in jsons assert_raises(json.JSONDecodeError, lambda: json.loads('{3: "abc"}')) assert_raises(json.JSONDecodeError, lambda: json_load('{3: "abc"}'))