Add 'mode' field to PydanticDumpOptions TypedDict
This is used when objects like IPv4Address or other custom objects is not reconised by the json serializer.
Often you want your model_dump to give you the object not serialized like IPv4Addresses, but you want model_dump(mode="json") to give you the string.
I would even suggest that mode="json" should be default, but I'm afraid that would break som peoples code.
from ipaddress import IPv4Address
import pydantic
class Demo(pydantic.BaseModel):
ip: IPv4Address
d = Demo(ip=IPv4Address("127.0.0.1"))
d.model_dump()
# {'ip': IPv4Address('127.0.0.1')}
d.model_dump(mode="json")
# {'ip': '127.0.0.1'}
I'm not sure this is required, the addition of a JSONEncoder here should ensure that it is converted to JSON
I can only have this working when I set mode
Without mode
from http import HTTPStatus
from ipaddress import IPv4Address
import pydantic
import quart_schema
from quart import Quart
class DemoResp(pydantic.BaseModel):
message: str
ip: IPv4Address
schema = quart_schema.QuartSchema()
app = Quart(__name__)
schema.init_app(app)
@app.get("/hello")
@quart_schema.validate_response(DemoResp, HTTPStatus.OK)
def hello() -> tuple[DemoResp, int]:
return DemoResp(message="Hello, World!", ip=IPv4Address("127.0.0.1")), HTTPStatus.OK
if __name__ == "__main__":
app.run(host="127.0.0.1", port=5000)
pydantic_core._pydantic_core.PydanticSerializationError: Unable to serialize unknown type: <class 'ipaddress.IPv4Address'>
[2025-12-03 09:37:49 +0100] [39524] [INFO] 127.0.0.1:60923 GET /hello 1.1 500 265 67192
With mode
from http import HTTPStatus
from ipaddress import IPv4Address
import pydantic
import quart_schema
from quart import Quart
class DemoResp(pydantic.BaseModel):
message: str
ip: IPv4Address
schema = quart_schema.QuartSchema()
app = Quart(__name__)
app.config["QUART_SCHEMA_PYDANTIC_DUMP_OPTIONS"] = {"mode": "json"}
schema.init_app(app)
@app.get("/hello")
@quart_schema.validate_response(DemoResp, HTTPStatus.OK)
def hello() -> tuple[DemoResp, int]:
return DemoResp(message="Hello, World!", ip=IPv4Address("127.0.0.1")), HTTPStatus.OK
if __name__ == "__main__":
app.run(host="127.0.0.1", port=5000)
[2025-12-03 09:39:29 +0100] [12112] [INFO] Running on http://127.0.0.1:5000 (CTRL + C to quit)
[2025-12-03 09:39:54 +0100] [12112] [INFO] 127.0.0.1:55864 GET /hello 1.1 200 45 8726
@pgjones And an example of some models that handles what I call stupid api xD
from http import HTTPStatus
import pydantic
import quart_schema
from quart import Quart
class StupidApiModel(pydantic.BaseModel):
name: str
version: str
@pydantic.field_validator("version", "name", mode="before")
@classmethod
def _validate_value_dict(cls, v: dict[str, str] | str) -> str:
if isinstance(v, str):
return v
return v["value"]
@pydantic.field_serializer("version", "name", when_used="json")
def _serialize_value_dict(self, v: str) -> dict[str, str]:
return {"value": v}
schema = quart_schema.QuartSchema()
app = Quart(__name__)
schema.init_app(app)
@app.get("/world")
@quart_schema.validate_response(StupidApiModel, HTTPStatus.OK)
def world() -> tuple[StupidApiModel, int]:
return StupidApiModel(name="World", version="1.0"), HTTPStatus.OK
if __name__ == "__main__":
app.run(host="127.0.0.1", port=5000)
This incorrectly returns {"name":"World","version":"1.0"}
With the json mode
from http import HTTPStatus
import pydantic
import quart_schema
from quart import Quart
class StupidApiModel(pydantic.BaseModel):
name: str
version: str
@pydantic.field_validator("version", "name", mode="before")
@classmethod
def _validate_value_dict(cls, v: dict[str, str] | str) -> str:
if isinstance(v, str):
return v
return v["value"]
@pydantic.field_serializer("version", "name", when_used="json")
def _serialize_value_dict(self, v: str) -> dict[str, str]:
return {"value": v}
schema = quart_schema.QuartSchema()
app = Quart(__name__)
app.config["QUART_SCHEMA_PYDANTIC_DUMP_OPTIONS"] = {"mode": "json"}
schema.init_app(app)
@app.get("/world")
@quart_schema.validate_response(StupidApiModel, HTTPStatus.OK)
def world() -> tuple[StupidApiModel, int]:
return StupidApiModel(name="World", version="1.0"), HTTPStatus.OK
if __name__ == "__main__":
app.run(host="127.0.0.1", port=5000)
Correctly returns {"name":{"value":"World"},"version":{"value":"1.0"}}
I'm not sure what is going wrong here, when I try
from http import HTTPStatus
from ipaddress import IPv4Address
import pydantic
import quart_schema
from quart import Quart
class DemoResp(pydantic.BaseModel):
message: str
ip: IPv4Address
schema = quart_schema.QuartSchema()
app = Quart(__name__)
schema.init_app(app)
@app.get("/hello")
@quart_schema.validate_response(DemoResp, HTTPStatus.OK)
def hello() -> tuple[DemoResp, int]:
return DemoResp(message="Hello, World!", ip=IPv4Address("127.0.0.1")), HTTPStatus.OK
if __name__ == "__main__":
app.run(host="127.0.0.1", port=5000)
it works.
Do you have the full stack trace for the pydantic_core._pydantic_core.PydanticSerializationError error?