Pydantic: Unable to serialize/validate while using “Union” with “Field” in response_model

Created on 22 Apr 2020  Â·  1Comment  Â·  Source: samuelcolvin/pydantic

Question

I'm trying to make the class TableSetting as BaseModel and take it as response_model. But seems like there are some validation or serialization errors in this class. I guess it might be Union or Optional[str] that I ues but not sure.

OS: Ubuntu 18.04.4 LTS
Python version: 3.7.7
Pydantic version: 1.4
from fastapi import FastAPI, Query, Body, Path
from pydantic import BaseModel, Field
from typing import Union, Optional
from enum import Enum


app = FastAPI()


class Tableware(str, Enum):
    SPOON= "SPOON"
    FORK= "FORK"

class TableSetting(BaseModel):
    kitchen: Union[Tableware, Optional[str]] = Field(..., title="I am title")
    numberOfknife: int = Field(None, ge=0, le=4)

@app.post(
    "/{tableNumber}/provide-table-setting",
    response_model= TableSetting,    
)

def provide_table_setting(
    *,
    tableNumber: str= Path(...),
):
    results = {"tableNumber": tableNumber}
    return results

The json schema of class TableSetting should look like this

TableSetting{
    kitchen*        I am title{
                        anyOf ->    string  
                                    Enum:
                                        [ SPOON, FORK ]
                                    string
                    }
    numberOfknife   integer
                    maximum: 4
                    minimum: 0
}

While performing curl
curl -X POST "http://localhost:8000/2/provide-table-setting" -H "accept: application/json"
it return errors as follows with response code 500, Internal Server Error , seems like some there are some validation problems with kitchen but I can't figure out why.

INFO:     127.0.0.1:53558 - "POST /2/provide-table-setting HTTP/1.1" 500 Internal Server Error
ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "/home/*****/miniconda3/envs/fastAPI/lib/python3.7/site-packages/uvicorn/protocols/http/httptools_impl.py", line 385, in run_asgi
    result = await app(self.scope, self.receive, self.send)
.
.
.
  File "/home/*****/miniconda3/envs/fastAPI/lib/python3.7/site-packages/fastapi/routing.py", line 126, in serialize_response
    raise ValidationError(errors, field.type_)
pydantic.error_wrappers.ValidationError: 1 validation error for TableSetting
response -> kitchen
  field required (type=value_error.missing)

However, when remove 1= Field(..., title="I a title")1 from the code as follows. It's works fine with a response code 200, but since I need 1Item kitchen1 as required, so it's not what I want.

class TableSetting(BaseModel):
    kitchen: Union[Tableware, Optional[str]]
    numberOfknife: int = Field(None, ge=0, le=4)

How can I fix this?

Thanks

question

Most helpful comment

Hi @GlennShih
When you write

kitchen: Union[Tableware, Optional[str]] = Field(..., title="I am title")

you expect kitchen to always be set no matter what because of the ... (required value)! You allow None as a valid value thanks to the Optional but that's it! See the doc for more details.
Since you only set tableNumber in your response, it raises an error !
If you want to make kitchen completely optional, you can just add a default value
Field(None, title='I am a title')

>All comments

Hi @GlennShih
When you write

kitchen: Union[Tableware, Optional[str]] = Field(..., title="I am title")

you expect kitchen to always be set no matter what because of the ... (required value)! You allow None as a valid value thanks to the Optional but that's it! See the doc for more details.
Since you only set tableNumber in your response, it raises an error !
If you want to make kitchen completely optional, you can just add a default value
Field(None, title='I am a title')

Was this page helpful?
0 / 5 - 0 ratings

Related issues

engstrom picture engstrom  Â·  3Comments

bartekbrak picture bartekbrak  Â·  3Comments

cdeil picture cdeil  Â·  3Comments

ashears picture ashears  Â·  3Comments

ashpreetbedi picture ashpreetbedi  Â·  3Comments