如何在使用Pydantic进入后转换有效负载数据



我有一个负载,它有两个参数。其中一个参数是包含更多参数的长字符串。像这样的param1%param2%param3。我使用FastAPI和Pydantic BaseModel来获取该数据并验证它,但是由于我在其他地方使用它,我也想转换它并将其存储在对象中,以便我可以稍后访问它,而不必在需要时转换它。比如PayloadObject.param1

from fastapi import FastAPI
from pydantic import BaseModel
class Payload(BaseModel):
string_params: str #param1%param2%param3
second_param: dict
@validator(string_params)
def string_params_validator(cls, strings_params):
#validation stuff
@validator(second_param)
def second_param(cls, second_param):
#validation stuff
app = FastAPI()
@app.post("/my_route")
async def post_my_route(payload: Payload):
# want to have transformed payload around here
func(payload)

使用pydantic最好的方法是什么?

我只是想做一个类,在不使用BaseModel的情况下转换__init__上的这些信息。因此,在我从请求中获得数据并对其进行验证之后,我在这个类中运行它并获得我满意的格式。

class NewPayload:
def __init__(self, payload: Payload):
# do transformations so i end up with
self.param1 = param1
self.param2 = param2
self.param3 = param3
self.second_param = second_param

如果此有效负载结构是特定于此路由的,那么最好直接在路由定义中对其进行转换。

如果参数的数量不总是相同,那么你给NewPayload的结构将不起作用。

示例1:

from typing import List
from fastapi import FastAPI
from pydantic import BaseModel
class Payload(BaseModel):
string_params: str #param1%param2%param3
second_param: dict
@validator(string_params)
def string_params_validator(cls, strings_params):
#validation stuff
@validator(second_param)
def second_param(cls, second_param):
#validation stuff
app = FastAPI()
@app.post("/my_route")
async def post_my_route(payload: Payload):
params: List[str] = payload.string_params.split("%")
# params = ["param1", "param2", "param3"]
# Do something with params
func(payload)

另一个想法:

不是最好的,因为你也接受列表格式的数据,你可以添加一个验证器来阻止这种行为,但它会修改doc

from typing import List
from fastapi import FastAPI
from pydantic import BaseModel
class Payload(BaseModel):
string_params: Union[str, List[str]] #param1%param2%param3
second_param: dict
@validator(string_params)
def string_params_validator(cls, strings_params):
string_params = strings_params.split("%")
return string_params

@validator(string_params)
def params_to_list(cls, strings_params):
#validation stuff
@validator(second_param)
def second_param(cls, second_param):
#validation stuff
app = FastAPI()
@app.post("/my_route")
async def post_my_route(payload: Payload):
func(payload)

您可以在第二个解决方案中使用第二个pydantic模型,只接受输入中的str,并将您的第一个模型转换为另一个。

from typing import List
from fastapi import FastAPI
from pydantic import BaseModel
class Payload(BaseModel):
string_params: str #param1%param2%param3
second_param: dict
@validator(string_params)
def params_to_list(cls, strings_params):
#validation stuff
@validator(second_param)
def second_param(cls, second_param):
#validation stuff
class Payload1(BaseModel):
string_params: Union[str, List[str]]
second_param: dict
@validator(string_params)
def string_params_validator(cls, strings_params):
string_params = strings_params.split("%")
return string_params
app = FastAPI()
@app.post("/my_route")
async def post_my_route(payload: Payload):
params: Payload1 = Payload1(**Payload.dict())
func(payload)
最后,更简洁的解决方案是使string_params成为一个str列表,而不是一个简单的str,因为您总是需要将其转换为list