Browse Source

🐛 Fix `jsonable_encoder` using `include` and `exclude` parameters for non-Pydantic objects (#2606)

Co-authored-by: Sebastián Ramírez <[email protected]>
pull/5283/head
Xavi Moreno 3 years ago
committed by GitHub
parent
commit
eb2e183361
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      fastapi/encoders.py
  2. 34
      tests/test_jsonable_encoder.py

9
fastapi/encoders.py

@ -80,6 +80,11 @@ def jsonable_encoder(
return obj
if isinstance(obj, dict):
encoded_dict = {}
allowed_keys = set(obj.keys())
if include is not None:
allowed_keys &= set(include)
if exclude is not None:
allowed_keys -= set(exclude)
for key, value in obj.items():
if (
(
@ -88,7 +93,7 @@ def jsonable_encoder(
or (not key.startswith("_sa"))
)
and (value is not None or not exclude_none)
and ((include and key in include) or not exclude or key not in exclude)
and key in allowed_keys
):
encoded_key = jsonable_encoder(
key,
@ -144,6 +149,8 @@ def jsonable_encoder(
raise ValueError(errors)
return jsonable_encoder(
data,
include=include,
exclude=exclude,
by_alias=by_alias,
exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults,

34
tests/test_jsonable_encoder.py

@ -93,16 +93,42 @@ def fixture_model_with_path(request):
return ModelWithPath(path=request.param("/foo", "bar"))
def test_encode_dict():
pet = {"name": "Firulais", "owner": {"name": "Foo"}}
assert jsonable_encoder(pet) == {"name": "Firulais", "owner": {"name": "Foo"}}
assert jsonable_encoder(pet, include={"name"}) == {"name": "Firulais"}
assert jsonable_encoder(pet, exclude={"owner"}) == {"name": "Firulais"}
assert jsonable_encoder(pet, include={}) == {}
assert jsonable_encoder(pet, exclude={}) == {
"name": "Firulais",
"owner": {"name": "Foo"},
}
def test_encode_class():
person = Person(name="Foo")
pet = Pet(owner=person, name="Firulais")
assert jsonable_encoder(pet) == {"name": "Firulais", "owner": {"name": "Foo"}}
assert jsonable_encoder(pet, include={"name"}) == {"name": "Firulais"}
assert jsonable_encoder(pet, exclude={"owner"}) == {"name": "Firulais"}
assert jsonable_encoder(pet, include={}) == {}
assert jsonable_encoder(pet, exclude={}) == {
"name": "Firulais",
"owner": {"name": "Foo"},
}
def test_encode_dictable():
person = DictablePerson(name="Foo")
pet = DictablePet(owner=person, name="Firulais")
assert jsonable_encoder(pet) == {"name": "Firulais", "owner": {"name": "Foo"}}
assert jsonable_encoder(pet, include={"name"}) == {"name": "Firulais"}
assert jsonable_encoder(pet, exclude={"owner"}) == {"name": "Firulais"}
assert jsonable_encoder(pet, include={}) == {}
assert jsonable_encoder(pet, exclude={}) == {
"name": "Firulais",
"owner": {"name": "Foo"},
}
def test_encode_unsupported():
@ -144,6 +170,14 @@ def test_encode_model_with_default():
assert jsonable_encoder(model, exclude_unset=True, exclude_defaults=True) == {
"foo": "foo"
}
assert jsonable_encoder(model, include={"foo"}) == {"foo": "foo"}
assert jsonable_encoder(model, exclude={"bla"}) == {"foo": "foo", "bar": "bar"}
assert jsonable_encoder(model, include={}) == {}
assert jsonable_encoder(model, exclude={}) == {
"foo": "foo",
"bar": "bar",
"bla": "bla",
}
def test_custom_encoders():

Loading…
Cancel
Save