Skip to content

Commit

Permalink
fix(jsonable_encoder): include and exclude parameters
Browse files Browse the repository at this point in the history
This fixes #2594. I added more few cases with include and exclude parameters, which were missing. Now the parameters are consistent with the way that it works with Pydantic.
  • Loading branch information
xaviml committed May 8, 2022
1 parent 9090c77 commit 9658135
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
9 changes: 8 additions & 1 deletion fastapi/encoders.py
Expand Up @@ -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 (
(
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
34 changes: 34 additions & 0 deletions tests/test_jsonable_encoder.py
Expand Up @@ -93,16 +93,42 @@ class Config:
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():
Expand Down Expand Up @@ -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():
Expand Down

0 comments on commit 9658135

Please sign in to comment.