Browse Source

Skip set(obj.keys()) allocation in jsonable_encoder when include/exclude are not set

pull/15476/head
Vittoria 1 month ago
committed by Vittoria Lanzo
parent
commit
e9cdebb73e
  1. 14
      fastapi/encoders.py
  2. 38
      tests/test_jsonable_encoder.py

14
fastapi/encoders.py

@ -280,11 +280,13 @@ def jsonable_encoder(
return None return None
if isinstance(obj, dict): if isinstance(obj, dict):
encoded_dict = {} encoded_dict = {}
allowed_keys = set(obj.keys()) allowed_keys: set[Any] | None = None
if include is not None: if include is not None or exclude is not None:
allowed_keys &= set(include) allowed_keys = set(obj.keys())
if exclude is not None: if include is not None:
allowed_keys -= set(exclude) allowed_keys &= set(include)
if exclude is not None:
allowed_keys -= set(exclude)
for key, value in obj.items(): for key, value in obj.items():
if ( if (
( (
@ -293,7 +295,7 @@ def jsonable_encoder(
or (not key.startswith("_sa")) or (not key.startswith("_sa"))
) )
and (value is not None or not exclude_none) and (value is not None or not exclude_none)
and key in allowed_keys and (allowed_keys is None or key in allowed_keys)
): ):
encoded_key = jsonable_encoder( encoded_key = jsonable_encoder(
key, key,

38
tests/test_jsonable_encoder.py

@ -329,3 +329,41 @@ def test_encode_color(module_path):
data = {"color": Color("blue")} data = {"color": Color("blue")}
assert jsonable_encoder(data) == {"color": "blue"} assert jsonable_encoder(data) == {"color": "blue"}
def test_dict_no_filter_returns_all_keys():
result = jsonable_encoder({"a": 1, "b": 2, "c": 3})
assert result == {"a": 1, "b": 2, "c": 3}
def test_dict_include_filters_correctly():
result = jsonable_encoder({"a": 1, "b": 2}, include={"a"})
assert result == {"a": 1}
def test_dict_exclude_filters_correctly():
result = jsonable_encoder({"a": 1, "b": 2}, exclude={"b"})
assert result == {"a": 1}
def test_dict_empty_include_returns_empty():
result = jsonable_encoder({"a": 1}, include=set())
assert result == {}
def test_dict_empty_exclude_returns_all():
result = jsonable_encoder({"a": 1}, exclude=set())
assert result == {"a": 1}
def test_dict_both_include_and_exclude():
result = jsonable_encoder(
{"a": 1, "b": 2, "c": 3}, include={"a", "b"}, exclude={"b"}
)
assert result == {"a": 1}
def test_encode_nested_dict():
nested = {"level1": {"level2": {"level3": 42}}}
result = jsonable_encoder(nested)
assert result == nested

Loading…
Cancel
Save