mirror of https://github.com/tiangolo/fastapi.git
✨ Support `dataclasses` in responses (#3576)
Co-authored-by: amit lissack <amit@opentrons.com>
This commit is contained in:
parent
49517d3310
commit
96fdfc53cc
|
|
@ -1,3 +1,4 @@
|
||||||
|
import dataclasses
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pathlib import PurePath
|
from pathlib import PurePath
|
||||||
|
|
@ -61,6 +62,8 @@ def jsonable_encoder(
|
||||||
custom_encoder=encoder,
|
custom_encoder=encoder,
|
||||||
sqlalchemy_safe=sqlalchemy_safe,
|
sqlalchemy_safe=sqlalchemy_safe,
|
||||||
)
|
)
|
||||||
|
if dataclasses.is_dataclass(obj):
|
||||||
|
return dataclasses.asdict(obj)
|
||||||
if isinstance(obj, Enum):
|
if isinstance(obj, Enum):
|
||||||
return obj.value
|
return obj.value
|
||||||
if isinstance(obj, PurePath):
|
if isinstance(obj, PurePath):
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import dataclasses
|
||||||
import email.message
|
import email.message
|
||||||
import enum
|
import enum
|
||||||
import inspect
|
import inspect
|
||||||
|
|
@ -90,6 +91,8 @@ def _prepare_response_content(
|
||||||
)
|
)
|
||||||
for k, v in res.items()
|
for k, v in res.items()
|
||||||
}
|
}
|
||||||
|
elif dataclasses.is_dataclass(res):
|
||||||
|
return dataclasses.asdict(res)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,11 @@ def get_valid():
|
||||||
return {"name": "valid", "price": 1.0}
|
return {"name": "valid", "price": 1.0}
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/items/object", response_model=Item)
|
||||||
|
def get_object():
|
||||||
|
return Item(name="object", price=1.0, owner_ids=[1, 2, 3])
|
||||||
|
|
||||||
|
|
||||||
@app.get("/items/coerce", response_model=Item)
|
@app.get("/items/coerce", response_model=Item)
|
||||||
def get_coerce():
|
def get_coerce():
|
||||||
return {"name": "coerce", "price": "1.0"}
|
return {"name": "coerce", "price": "1.0"}
|
||||||
|
|
@ -33,6 +38,29 @@ def get_validlist():
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/items/objectlist", response_model=List[Item])
|
||||||
|
def get_objectlist():
|
||||||
|
return [
|
||||||
|
Item(name="foo"),
|
||||||
|
Item(name="bar", price=1.0),
|
||||||
|
Item(name="baz", price=2.0, owner_ids=[1, 2, 3]),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/items/no-response-model/object")
|
||||||
|
def get_no_response_model_object():
|
||||||
|
return Item(name="object", price=1.0, owner_ids=[1, 2, 3])
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/items/no-response-model/objectlist")
|
||||||
|
def get_no_response_model_objectlist():
|
||||||
|
return [
|
||||||
|
Item(name="foo"),
|
||||||
|
Item(name="bar", price=1.0),
|
||||||
|
Item(name="baz", price=2.0, owner_ids=[1, 2, 3]),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -42,6 +70,12 @@ def test_valid():
|
||||||
assert response.json() == {"name": "valid", "price": 1.0, "owner_ids": None}
|
assert response.json() == {"name": "valid", "price": 1.0, "owner_ids": None}
|
||||||
|
|
||||||
|
|
||||||
|
def test_object():
|
||||||
|
response = client.get("/items/object")
|
||||||
|
response.raise_for_status()
|
||||||
|
assert response.json() == {"name": "object", "price": 1.0, "owner_ids": [1, 2, 3]}
|
||||||
|
|
||||||
|
|
||||||
def test_coerce():
|
def test_coerce():
|
||||||
response = client.get("/items/coerce")
|
response = client.get("/items/coerce")
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
@ -56,3 +90,29 @@ def test_validlist():
|
||||||
{"name": "bar", "price": 1.0, "owner_ids": None},
|
{"name": "bar", "price": 1.0, "owner_ids": None},
|
||||||
{"name": "baz", "price": 2.0, "owner_ids": [1, 2, 3]},
|
{"name": "baz", "price": 2.0, "owner_ids": [1, 2, 3]},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_objectlist():
|
||||||
|
response = client.get("/items/objectlist")
|
||||||
|
response.raise_for_status()
|
||||||
|
assert response.json() == [
|
||||||
|
{"name": "foo", "price": None, "owner_ids": None},
|
||||||
|
{"name": "bar", "price": 1.0, "owner_ids": None},
|
||||||
|
{"name": "baz", "price": 2.0, "owner_ids": [1, 2, 3]},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_response_model_object():
|
||||||
|
response = client.get("/items/no-response-model/object")
|
||||||
|
response.raise_for_status()
|
||||||
|
assert response.json() == {"name": "object", "price": 1.0, "owner_ids": [1, 2, 3]}
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_response_model_objectlist():
|
||||||
|
response = client.get("/items/no-response-model/objectlist")
|
||||||
|
response.raise_for_status()
|
||||||
|
assert response.json() == [
|
||||||
|
{"name": "foo", "price": None, "owner_ids": None},
|
||||||
|
{"name": "bar", "price": 1.0, "owner_ids": None},
|
||||||
|
{"name": "baz", "price": 2.0, "owner_ids": [1, 2, 3]},
|
||||||
|
]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue