diff --git a/fastapi/encoders.py b/fastapi/encoders.py index 82e3ffa06..f5059a76f 100644 --- a/fastapi/encoders.py +++ b/fastapi/encoders.py @@ -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))): diff --git a/tests/test_datetime.py b/tests/test_datetime_custom_encoder.py similarity index 81% rename from tests/test_datetime.py rename to tests/test_datetime_custom_encoder.py index c16166ca4..75b40b3bf 100644 --- a/tests/test_datetime.py +++ b/tests/test_datetime_custom_encoder.py @@ -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"} diff --git a/tests/test_jsonable_encoder.py b/tests/test_jsonable_encoder.py index 9108df9d8..92eb34a78 100644 --- a/tests/test_jsonable_encoder.py +++ b/tests/test_jsonable_encoder.py @@ -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"}