Browse Source

perf: optimize jsonable_encoder by skipping redundant recursive calls for Pydantic models and add benchmarking and performance tests

pull/15965/head
Your Name 2 weeks ago
parent
commit
311e14b3dc
  1. 12
      fastapi/encoders.py
  2. 52
      tests/test_encoder_performance.py

12
fastapi/encoders.py

@ -250,12 +250,12 @@ def jsonable_encoder(
exclude_none=exclude_none,
exclude_defaults=exclude_defaults,
)
return jsonable_encoder(
obj_dict,
exclude_none=exclude_none,
exclude_defaults=exclude_defaults,
sqlalchemy_safe=sqlalchemy_safe,
)
if not sqlalchemy_safe:
return obj_dict
return {
k: v for k, v in obj_dict.items()
if not (isinstance(k, str) and k.startswith("_sa"))
}
if dataclasses.is_dataclass(obj):
assert not isinstance(obj, type)
obj_dict = dataclasses.asdict(obj)

52
tests/test_encoder_performance.py

@ -0,0 +1,52 @@
from typing import List, Optional
from pydantic import BaseModel
from fastapi.encoders import jsonable_encoder
class SubModel(BaseModel):
name: str
value: int = 42
class MainModel(BaseModel):
id: int
title: str
sub: SubModel
items: List[SubModel]
maybe: Optional[str] = None
_sa_instance_state: str = "should-be-removed"
def test_basemodel_serialization_correctness():
sub = SubModel(name="test")
model = MainModel(
id=1,
title="hello",
sub=sub,
items=[sub, SubModel(name="another", value=10)],
)
# 1. Standard serialization
encoded = jsonable_encoder(model)
assert encoded == {
"id": 1,
"title": "hello",
"sub": {"name": "test", "value": 42},
"items": [
{"name": "test", "value": 42},
{"name": "another", "value": 10},
],
"maybe": None,
}
# 2. Exclude none
encoded_exclude_none = jsonable_encoder(model, exclude_none=True)
assert "maybe" not in encoded_exclude_none
# 3. Include and Exclude parameter filtering
encoded_filtered = jsonable_encoder(model, include={"id", "title"})
assert encoded_filtered == {"id": 1, "title": "hello"}
encoded_excluded = jsonable_encoder(model, exclude={"sub", "items"})
assert "sub" not in encoded_excluded
assert "items" not in encoded_excluded
Loading…
Cancel
Save