FastAPI学习-15.JSON 编码器 jsonable_encoder
前言
在某些情况下,您可能需要将数据类型(如Pydantic模型)转换为与JSON兼容的数据类型(如dict
、list
等)。
比如,如果您需要将其存储在数据库中。
对于这种要求, FastAPI提供了jsonable_encoder()
函数。
使用jsonable_encoder
jsonable_encoder
- 在实际应用场景中,可能需要将数据类型(如:Pydantic 模型)转换为与 JSON 兼容的类型(如:字典、列表)
- 比如:需要将数据存储在数据库中
- 为此,FastAPI 提供了一个 jsonable_encoder() 函数
- jsonable_encoder 实际上是 FastAPI 内部用来转换数据的,但它在许多其他场景中很有用
需求
- 假设有一个仅接收兼容 JSON 数据的数据库 fake_db
- 例如,它不接收日期时间对象,因为这些对象与 JSON 不兼容
- 因此,必须将日期时间对象转换为包含 ISO 格式数据的 str
- 同样,这个数据库不会接收 Pydantic 模型(具有属性的对象),只会接收 dict
- 使用 jsonable_encoder 将数据转换成 dict
让我们假设你有一个数据库名为fake_db
,它只能接收与 JSON 兼容的数据。
from datetime import datetime
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
# 模拟数据库
fake_db = {}
class Item(BaseModel):
title: str
timestamp: datetime
description: Union[str, None] = None
@app.post("/items/{pk}")
def update_item(pk: str, item: Item):
# 新版2.x item.model_dump() 旧版1.x item.dict()
print(f"转成dict类型:{item.dict()}")
# 新版2.x item.model_dump_json() 旧版1.x item.json()
print(f"转成json类型:{item.json()}")
fake_db[pk] = item.dict()
print(f"得到数据:{fake_db}")
return fake_db
请求接口
POST http://127.0.0.1:8000/items/22 HTTP/1.1
User-Agent: Fiddler
Host: 127.0.0.1:8000
Content-Type: application/json
Content-Length: 86
{
"title": 22,
"timestamp": "2023-09-16 10:45:00",
"description": "描述"
}
运行结果
转成dict类型:{'title': '22', 'timestamp': datetime.datetime(2023, 9, 16, 10, 45), 'description': '描述'}
转成json类型:{"title": "22", "timestamp": "2023-09-16T10:45:00", "description": "\u63cf\u8ff0"}
得到数据:{'22': {'title': '22', 'timestamp': datetime.datetime(2023, 9, 16, 10, 45), 'description': '描述'}}
Pydantic模型可以通过item.dict()
转成字典对象 (**新版2.x item.model_dump() 旧版1.x item.dict() ** )
{'title': '22', 'timestamp': datetime.datetime(2023, 9, 16, 10, 45), 'description': '描述'}
由于 timestamp 是 datetime
这类的对象,它不能通过json.dumps()
转成 json 对象。
我们想得到标准能转 json的 dict 格式,有 2 种实现方式
-
item.json()
得到标准 json (**新版2.x item.model_dump_json() 旧版1.x item.json() **)。再使用json.loads()
转字典
- 2.使用
jsonable_encoder
方法一:
可以通过
item.item.json()
得到json格式数据
{"title": "22", "timestamp": "2023-09-16T10:45:00", "description": "\u63cf\u8ff0"}
再使用json.loads()
转字典
json.loads(item.json())
这样就可以得到可以转json的dict
{'title': '22', 'timestamp': '2023-09-16T10:45:00', 'description': '描述'}
方法二 :
使用fastapi 提供的 内置函数jsonable_encoder
from fastapi.encoders import jsonable_encoder
@app.post("/items/{pk}")
def update_item(pk: str, item: Item):
json_item = jsonable_encoder(item)
print(f"jsonable_encoder: {json_item}")
fake_db[pk] = item.dict()
print(f"得到数据:{fake_db}")
return fake_db
运行结果
jsonable_encoder: {'title': '22', 'timestamp': '2023-09-16T10:45:00', 'description': '描述'}
得到数据:{'22': {'title': '22', 'timestamp': datetime.datetime(2023, 9, 16, 10, 45), 'description': '描述'}}
在这个例子中,它将Pydantic模型转换为dict
,并将datetime
转换为str
。
它将返回一个Python标准数据结构(例如dict
),其值和子值都与JSON兼容。
调用它的结果后就可以使用 Python 标准编码中的 json.dumps()
jsonable_encoder
实际上是FastAPI内部用来转换数据的。但是它在许多其他场景中也很有用。