如何使用 Pydantic 转换有效负载数据

问题描述 投票:0回答:2

我有一个有效负载,其中有两个参数。其中一个参数是一长串,其中包含更多参数。像这样

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
python fastapi pydantic
2个回答
0
投票

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

如果参数数量不总是相同,您为 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)

另一个想法

这不是最好的,因为您也接受列表格式的数据,您可以添加验证器来阻止此行为,但它会修改文档

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,因为您始终需要将其转换为列表


0
投票

在 Pydantic v2 中,如果您想对整个实例应用验证,可以使用 @model_validator。拥有实例后,您可以为其分配任意属性:

...

class Payload(BaseModel):
    string_params: str  #param1%param2%param3
    second_param: dict

    @model_validator(mode='after')
    def string_params_validator(self):
        string_params = self.strings_params.split("%")
        for string_param in string_params:
            setattr(self, string_param, string_param)
        return self

...
© www.soinside.com 2019 - 2024. All rights reserved.