]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
:bug: Fix jsonable_encoder for models with Config (#29)
authorSebastián Ramírez <tiangolo@gmail.com>
Tue, 12 Feb 2019 17:43:34 +0000 (21:43 +0400)
committerGitHub <noreply@github.com>
Tue, 12 Feb 2019 17:43:34 +0000 (21:43 +0400)
but without json_encoders

fastapi/encoders.py
tests/test_datetime_custom_encoder.py [moved from tests/test_datetime.py with 81% similarity]
tests/test_jsonable_encoder.py

index 82e3ffa06c5f646a60ddac419d57435957e60bd0..f5059a76f33147cfd76750fc86dd0087e132c062 100644 (file)
@@ -15,17 +15,12 @@ def jsonable_encoder(
     custom_encoder: dict = {},
 ) -> Any:
     if isinstance(obj, BaseModel):
-        if not obj.Config.json_encoders:
-            return jsonable_encoder(
-                obj.dict(include=include, exclude=exclude, by_alias=by_alias),
-                include_none=include_none,
-            )
-        else:
-            return jsonable_encoder(
-                obj.dict(include=include, exclude=exclude, by_alias=by_alias),
-                include_none=include_none,
-                custom_encoder=obj.Config.json_encoders,
-            )
+        encoder = getattr(obj.Config, "json_encoders", custom_encoder)
+        return jsonable_encoder(
+            obj.dict(include=include, exclude=exclude, by_alias=by_alias),
+            include_none=include_none,
+            custom_encoder=encoder,
+        )
     if isinstance(obj, Enum):
         return obj.value
     if isinstance(obj, (str, int, float, type(None))):
similarity index 81%
rename from tests/test_datetime.py
rename to tests/test_datetime_custom_encoder.py
index c16166ca47ee15919ac091e08a021a8a1a15eb96..75b40b3bf2c373e00aee761bc5b1ce04f933776f 100644 (file)
@@ -1,4 +1,3 @@
-import json
 from datetime import datetime, timezone
 
 from fastapi import FastAPI
@@ -18,7 +17,7 @@ class ModelWithDatetimeField(BaseModel):
 
 
 app = FastAPI()
-model = ModelWithDatetimeField(dt_field=datetime.utcnow())
+model = ModelWithDatetimeField(dt_field=datetime(2019, 1, 1, 8))
 
 
 @app.get("/model", response_model=ModelWithDatetimeField)
@@ -32,4 +31,4 @@ client = TestClient(app)
 def test_dt():
     with client:
         response = client.get("/model")
-    assert json.loads(model.json()) == response.json()
+    assert response.json() == {"dt_field": "2019-01-01T08:00:00+00:00"}
index 9108df9d88a8686994cc3bbdea7a6492813124c0..92eb34a785914f9bcd7a164858614ce116d90c5e 100644 (file)
@@ -1,5 +1,9 @@
+from datetime import datetime, timezone
+from enum import Enum
+
 import pytest
 from fastapi.encoders import jsonable_encoder
+from pydantic import BaseModel
 
 
 class Person:
@@ -32,6 +36,29 @@ class Unserializable:
         raise NotImplementedError()
 
 
+class ModelWithCustomEncoder(BaseModel):
+    dt_field: datetime
+
+    class Config:
+        json_encoders = {
+            datetime: lambda dt: dt.replace(
+                microsecond=0, tzinfo=timezone.utc
+            ).isoformat()
+        }
+
+
+class RoleEnum(Enum):
+    admin = "admin"
+    normal = "normal"
+
+
+class ModelWithConfig(BaseModel):
+    role: RoleEnum = None
+
+    class Config:
+        use_enum_values = True
+
+
 def test_encode_class():
     person = Person(name="Foo")
     pet = Pet(owner=person, name="Firulais")
@@ -48,3 +75,13 @@ def test_encode_unsupported():
     unserializable = Unserializable()
     with pytest.raises(ValueError):
         jsonable_encoder(unserializable)
+
+
+def test_encode_custom_json_encoders_model():
+    model = ModelWithCustomEncoder(dt_field=datetime(2019, 1, 1, 8))
+    assert jsonable_encoder(model) == {"dt_field": "2019-01-01T08:00:00+00:00"}
+
+
+def test_encode_model_with_config():
+    model = ModelWithConfig(role=RoleEnum.admin)
+    assert jsonable_encoder(model) == {"role": "admin"}