Skip to content

Instantly share code, notes, and snippets.

@ndricca
Last active October 4, 2022 09:12
Show Gist options
  • Save ndricca/00ccd06e57d4ca932e8ca15cfda54c66 to your computer and use it in GitHub Desktop.
Save ndricca/00ccd06e57d4ca932e8ca15cfda54c66 to your computer and use it in GitHub Desktop.
[SOLVED] Stack Overflow question on FastAPI
from typing import Optional, List, Union
from typing_extensions import Literal
import uvicorn
from pydantic import BaseModel, Field
from fastapi import FastAPI, Body
class Payload(BaseModel):
start: int
end: int
class Link(BaseModel):
source: int
target: int
type: str
class SchoolNode(BaseModel):
id: int
label: Literal['school']
code: Optional[str]
class PersonNode(BaseModel):
id: int
label: Literal['person']
name: Optional[str]
surname: Optional[str]
class PetNode(BaseModel):
id: int
label: Literal['pet']
name: Optional[str]
surname: Optional[str]
class UnionNode(BaseModel):
__root__: Union[SchoolNode, PersonNode, PetNode] = Field(..., discriminator='label')
class Response(BaseModel):
links: List[Link]
nodes: List[UnionNode]
start: int
end: int
app = FastAPI()
@app.post("/shortest-path", response_model=Response)
def compute_shortest_path(payload: Payload = Body(
...
)):
# do_stuff
graph = {
'links': [
{'source': payload.start, 'target': 123, 'type': 'GO_TO_SCHOOL'},
{'source': 123, 'target': payload.end, 'type': 'GO_TO_SCHOOL'},
],
'nodes': [
{'id': payload.start, 'label': 'person', 'name': 'Bob', 'surname': 'Foo'},
{'id': 123, 'label': 'school', 'code': 'ABCD'},
{'id': payload.end, 'label': 'person', 'name': 'Alice', 'surname': 'Bar'}
],
'start': payload.start,
'end': payload.end
}
return Response(**graph)
if __name__ == '__main__':
uvicorn.run("fastapi_error_example:app")
@ndricca
Copy link
Author

ndricca commented Oct 4, 2022

The solution was creating a unique model UnionNode with a __root__ property with Field(..., discriminator='label').
Moreover, label property in nodes must have a Literal typing, here imported from typing_extensions for Python version < 3.8 compatibility.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment