]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
🐛 Fix `jsonable_encoder` using `include` and `exclude` parameters for non-Pydantic...
authorXavi Moreno <xaviml.93@gmail.com>
Thu, 18 Aug 2022 20:48:21 +0000 (06:48 +1000)
committerGitHub <noreply@github.com>
Thu, 18 Aug 2022 20:48:21 +0000 (22:48 +0200)
Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
fastapi/encoders.py
tests/test_jsonable_encoder.py

index 4b7ffe313fa6bf841c0ca25de577cb0716607a6a..b1fde73ceb7fcddda1b48b4533f5020f1223306a 100644 (file)
@@ -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,
index ed35fd32e43f0015e2b0448e9633fc587f8faaae..5e55f2f918467f97bf066d61670872a24a4a9d13 100644 (file)
@@ -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():