news 2026/11/6 3:49:09

FastApi(5)声明请求示例数据额外数据类型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FastApi(5)声明请求示例数据额外数据类型

作者学习fastapi文档时整理,欢迎各位查看

十一、声明请求示例数据

你可以为你的应用将接收的数据声明示例。

这里有几种实现方式。

1、Pydantic 模型中的额外 JSON Schema 数据

你可以为一个 Pydantic 模型声明examples,它们会被添加到生成的 JSON Schema 中。

fromfastapiimportFastAPIfrompydanticimportBaseModel app=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=Nonemodel_config={"json_schema_extra":{"examples":[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,}]}}@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults

这些额外信息会原样添加到该模型输出的JSON Schema中,并会在 API 文档中使用。

你可以使用属性model_config,它接收一个dict

你可以设置"json_schema_extra",其值为一个dict,包含你希望出现在生成 JSON Schema 中的任意附加数据,包括examples。

  • 提示

你也可以用同样的技巧扩展 JSON Schema,添加你自己的自定义额外信息。

例如,你可以用它为前端用户界面添加元数据等。

注意

OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)增加了对examples的支持,它是JSON Schema标准的一部分。

在此之前,只支持使用单个示例的关键字example。OpenAPI 3.1.0 仍然支持它,但它已被弃用,并不属于 JSON Schema 标准。因此,建议你把example迁移到examples。

2、Field的附加参数

在 Pydantic 模型中使用Field()时,你也可以声明额外的examples:

fromfastapiimportFastAPIfrompydanticimportBaseModel,Field app=FastAPI()classItem(BaseModel):name:str=Field(examples=["Foo"])description:str|None=Field(default=None,examples=["A very nice Item"])price:float=Field(examples=[35.4])tax:float|None=Field(default=None,examples=[3.2])@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item):results={"item_id":item_id,"item":item}returnresults

3、JSON Schema 中的examples- OpenAPI

在以下任意场景中使用:

  • Path()
  • Query()
  • Header()
  • Cookie()
  • Body()
  • Form()
  • File()

你也可以声明一组examples,这些带有附加信息的示例将被添加到它们在OpenAPI中的JSON Schema里。

带有examples的Body

这里我们向Body()传入examples,其中包含一个期望的数据示例:

fromtypingimportAnnotatedfromfastapiimportBody,FastAPIfrompydanticimportBaseModel app=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=None@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Annotated[Item,Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,}],),],):results={"item_id":item_id,"item":item}returnresults

其他版本:non-annotated

fromfastapiimportBody,FastAPIfrompydanticimportBaseModel app=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=None@app.put("/items/{item_id}")asyncdefupdate_item(item_id:int,item:Item=Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,}],),):results={"item_id":item_id,"item":item}returnresults

带有多个examples的Body

当然,你也可以传入多个examples:

fromtypingimportAnnotatedfromfastapiimportBody,FastAPIfrompydanticimportBaseModel app=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Annotated[Item,Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},{"name":"Bar","price":"35.4",},{"name":"Baz","price":"thirty five point four",},],),],):results={"item_id":item_id,"item":item}returnresults

其他版本:non-annotated

fromfastapiimportBody,FastAPIfrompydanticimportBaseModel app=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Item=Body(examples=[{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},{"name":"Bar","price":"35.4",},{"name":"Baz","price":"thirty five point four",},],),):results={"item_id":item_id,"item":item}returnresults

这样做时,这些示例会成为该请求体数据内部JSON Schema的一部分。

不过,在撰写本文时,用于展示文档 UI 的 Swagger UI 并不支持显示JSON Schema中数据的多个示例,但有一种变通方法。

OpenAPI 特定的examples

在JSON Schema支持examples之前,OpenAPI 就已支持一个同名但不同的字段examples。

这个OpenAPI 特定的examples位于 OpenAPI 规范的另一处。它放在每个*路径操作*的详细信息中,而不是每个 JSON Schema 里。

而 Swagger UI 早就支持这个特定的examples字段。因此,你可以用它在文档 UI 中展示不同的示例。

这个 OpenAPI 特定字段examples的结构是一个包含多个示例的dict(而不是一个list),每个示例都包含会被添加到OpenAPI的额外信息。

这不放在 OpenAPI 内部包含的各个 JSON Schema 里,而是直接放在路径操作上。

使用openapi_examples参数

你可以在 FastAPI 中通过参数openapi_examples来声明这个 OpenAPI 特定的examples,适用于:

  • Path()
  • Query()
  • Header()
  • Cookie()
  • Body()
  • Form()
  • File()

这个dict的键用于标识每个示例,每个值是另一个dict。

examples中每个具体示例的dict可以包含:

  • summary:该示例的简短描述。
  • description:较长描述,可以包含 Markdown 文本。
  • value:实际展示的示例,例如一个dict。
  • externalValue:value的替代项,指向该示例的 URL。不过它的工具支持度可能不如value。

你可以这样使用:

fromtypingimportAnnotatedfromfastapiimportBody,FastAPIfrompydanticimportBaseModel app=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Annotated[Item,Body(openapi_examples={"normal":{"summary":"A normal example","description":"A **normal** item works correctly.","value":{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},},"converted":{"summary":"An example with converted data","description":"FastAPI can convert price `strings` to actual `numbers` automatically","value":{"name":"Bar","price":"35.4",},},"invalid":{"summary":"Invalid data is rejected with an error","value":{"name":"Baz","price":"thirty five point four",},},},),],):results={"item_id":item_id,"item":item}returnresults

其他版本:

fromfastapiimportBody,FastAPIfrompydanticimportBaseModel app=FastAPI()classItem(BaseModel):name:strdescription:str|None=Noneprice:floattax:float|None=None@app.put("/items/{item_id}")asyncdefupdate_item(*,item_id:int,item:Item=Body(openapi_examples={"normal":{"summary":"A normal example","description":"A **normal** item works correctly.","value":{"name":"Foo","description":"A very nice Item","price":35.4,"tax":3.2,},},"converted":{"summary":"An example with converted data","description":"FastAPI can convert price `strings` to actual `numbers` automatically","value":{"name":"Bar","price":"35.4",},},"invalid":{"summary":"Invalid data is rejected with an error","value":{"name":"Baz","price":"thirty five point four",},},},),):results={"item_id":item_id,"item":item}returnresults

4、技术细节

  • 注:

此部分针对于FastAPI版本 **0.99.0以下版本 **。

它们对更早版本(OpenAPI 3.1.0 尚不可用之前)更相关。

在 OpenAPI 3.1.0 之前,OpenAPI 使用的是一个更旧且经过修改的JSON Schema版本。

当时 JSON Schema 没有examples,所以 OpenAPI 在它修改过的版本中添加了自己的example字段。

OpenAPI 还在规范的其他部分添加了example和examples字段:

  • Parameter Object(规范中)

    ,被 FastAPI 的以下内容使用:

    • Path()
    • Query()
    • Header()
    • Cookie()
  • Request Body Object中的content字段里的Media Type Object(规范中)

    ,被 FastAPI 的以下内容使用:

    • Body()
    • File()
    • Form()

注意

这个旧的、OpenAPI 特定的examples参数,自 FastAPI0.103.0起改名为openapi_examples。

JSON Schema 的examples字段

后来,JSON Schema 在新版本的规范中添加了examples字段。

随后新的 OpenAPI 3.1.0 基于最新版本(JSON Schema 2020-12),其中包含了这个新的examples字段。

现在,这个新的examples字段优先于旧的单个(且自定义的)example字段,后者已被弃用。

在 JSON Schema 中,这个新的examples字段只是一个由示例组成的list,而不是像上面提到的 OpenAPI 其他位置那样带有额外元数据的dict。

注意

即使在 OpenAPI 3.1.0 发布、并与 JSON Schema 有了这种更简单的集成之后,有一段时间里,提供自动文档的 Swagger UI 并不支持 OpenAPI 3.1.0(它自 5.0.0 版本起已支持 )。

因此,FastAPI 0.99.0 之前的版本仍然使用低于 3.1.0 的 OpenAPI 版本。

Pydantic 与 FastAPI 的examples

当你在 Pydantic 模型中添加examples,通过schema_extra或Field(examples=["something"]),这些示例会被添加到该 Pydantic 模型的JSON Schema中。

这个 Pydantic 模型的JSON Schema会被包含到你的 API 的OpenAPI中,然后在文档 UI 中使用。

在 FastAPI 0.99.0 之前的版本(0.99.0 及以上使用更新的 OpenAPI 3.1.0),当你在其他工具(Query()、Body()等)中使用example或examples时,这些示例不会被添加到描述该数据的 JSON Schema 中(甚至不会添加到 OpenAPI 自己的 JSON Schema 版本中),而是会直接添加到 OpenAPI 的路径操作声明中(在 OpenAPI 使用 JSON Schema 的部分之外)。

但现在 FastAPI 0.99.0 及以上使用 OpenAPI 3.1.0(其使用 JSON Schema 2020-12)以及 Swagger UI 5.0.0 及以上后,一切更加一致,示例会包含在 JSON Schema 中。

Swagger UI 与 OpenAPI 特定的examples

由于截至 2023-08-26,Swagger UI 不支持多个 JSON Schema 示例,用户无法在文档中展示多个示例。

为了解决这个问题,FastAPI0.103.0增加了支持,可以通过新参数openapi_examples声明同样的旧式OpenAPI 特定的examples字段。

十二、额外数据类型

我们一直在使用常见的数据类型,如:

  • int
  • float
  • str
  • bool

但是也可以使用更复杂的数据类型,仍然会拥有现在已经看到的相同的特性:

  • 很棒的编辑器支持。
  • 传入请求的数据转换。
  • 响应数据转换。
  • 数据验证。
  • 自动注解和文档。

1、其他数据类型

下面是一些你可以使用的其他数据类型:

  • UUID
    • 一种标准的 “通用唯一标识符” ,在许多数据库和系统中用作ID。
    • 在请求和响应中将以str表示。
  • datetime.datetime
    • 一个 Pythondatetime.datetime.
    • 在请求和响应中将表示为 ISO 8601 格式的str,比如:2008-09-15T15:53:00+05:00.
  • datetime.date
    • Pythondatetime.date.
    • 在请求和响应中将表示为 ISO 8601 格式的str,比如:2008-09-15.
  • datetime.time
    • 一个 Pythondatetime.time.
    • 在请求和响应中将表示为 ISO 8601 格式的str,比如:14:23:55.003.
  • datetime.timedelta
    • 一个 Pythondatetime.timedelta.
    • 在请求和响应中将表示为float代表总秒数。
    • Pydantic 也允许将其表示为 “ISO 8601 时间差异编码”, 查看文档了解更多信息。
  • frozenset
    • 在请求和响应中,作为 set对待:
      • 在请求中,列表将被读取,消除重复,并将其转换为一个set。
      • 在响应中set将被转换为list。
      • 产生的模式将指定那些set的值是唯一的 (使用 JSON Schema 的uniqueItems)。
  • bytes
    • 标准的 Pythonbytes。
    • 在请求和响应中被当作str处理。
    • 生成的模式将指定这个str是binary“格式”。
  • Decimal
    • 标准的 PythonDecimal。
    • 在请求和响应中被当做float一样处理。

2、例

下面是一个路径操作的示例,其中的参数使用了上面的一些类型。

注意,函数内的参数有原生的数据类型,例如,你可以执行正常的日期操作

fromdatetimeimportdatetime,time,timedeltafromtypingimportAnnotatedfromuuidimportUUIDfromfastapiimportBody,FastAPI app=FastAPI()@app.put("/items/{item_id}")asyncdefread_items(item_id:UUID,start_datetime:Annotated[datetime,Body()],end_datetime:Annotated[datetime,Body()],process_after:Annotated[timedelta,Body()],repeat_at:Annotated[time|None,Body()]=None,):start_process=start_datetime+process_after duration=end_datetime-start_processreturn{"item_id":item_id,"start_datetime":start_datetime,"end_datetime":end_datetime,"process_after":process_after,"repeat_at":repeat_at,"start_process":start_process,"duration":duration,}

其他版本:non_annotated

fromdatetimeimportdatetime,time,timedeltafromuuidimportUUIDfromfastapiimportBody,FastAPI app=FastAPI()@app.put("/items/{item_id}")asyncdefread_items(item_id:UUID,start_datetime:datetime=Body(),end_datetime:datetime=Body(),process_after:timedelta=Body(),repeat_at:time|None=Body(default=None),):start_process=start_datetime+process_after duration=end_datetime-start_processreturn{"item_id":item_id,"start_datetime":start_datetime,"end_datetime":end_datetime,"process_after":process_after,"repeat_at":repeat_at,"start_process":start_process,"duration":duration,}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/6 3:48:09

概念模型怎么搭出来:从变量关系到可画可讲的模型图

开题会被要求"画一个概念模型图",卡住的往往不是软件,而是逻辑没成形:变量有哪些、谁指向谁、这条线凭什么连。概念模型不是装饰图,它是研究问题的一次公开翻译。下面按认变量、定方向、画图、讲图四个动作走。先认清变…

作者头像 李华
网站建设 2026/11/6 3:47:09

PostGIS实现矢量瓦片之生成 Mapbox 矢量瓦片【ST_AsMVT】

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/6 3:47:03

Linux、Shell、MySQL 测试卷逐题细讲(下篇:MySQL)

三、MySQL1. 填空题(1)计算行数并忽略 NULL 的函数题目: 使用 ______ 函数可以计算查询结果的行数,并忽略 NULL 值。答案: COUNT()展开讲:SELECT COUNT(commission_pct) FROM employees;COUNT(列名) 只统计…

作者头像 李华
网站建设 2026/11/6 3:45:27

157_求解失败不可行怎么查

这一章要解决什么 小林在期末前第 4 周给自己排晚自习。他给自己定的规矩只有两条:一周要坐满 20 小时;每晚不超过 2 小时,超过就睡不够。周一到周五能排,周末回家,所以一周只有 5 个晚上。两条规矩加"只有五天&q…

作者头像 李华
网站建设 2026/11/6 3:45:19

直播平台带宽成本降低 40% 实录:FFmpeg 转码链路与自适应码率实践

摘要:主导过一个流媒体直播平台的建设:接入海康威视等 10+ 品牌监控/教学硬件,日均直播时长超 2 万小时,万级并发观看。带宽是这类平台最大的成本项,我们通过转码参数优化 + 自适应码率 + 分辨率策略的组合拳,把带宽成本降低了约 40%。这篇文章讲完整链路:监控摄像头怎么…

作者头像 李华