Pydantic v2 与请求 POST JSON - “不可序列化”噩梦

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

我正在编写一个脚本,将数据从内部系统发布到第三方 Web API。我们的内部系统使用 Pydantic 中定义的数据模型。我正在尝试使用

requests.post
将这些模型之一中的数据发送到 API,但它无法序列化某些类型,这让我发疯。

以此数据模型为例:

class Product(BaseModel):
    id: int
    group_id: int
    sku: str
    price: Decimal
    special_offer_price: Decimal
    last_update: datetime.date

如果我尝试使用此模型使用

requests.post
发送数据,则:

product_item = website_api.Product(**product.__dict__)

requests.post(url, headers=jwt_auth.auth_header, json=product_item)

str
int
字段很好,但是
Decimal
datetime.date
字段会抛出异常,因为它们不可序列化,给出的错误有点像:

TypeError: Object of type date is not JSON serializable

我尝试将字段的

@field_serializer
添加到 pydantic 的类定义中;

    @field_serializer("price", "special_offer_price")
    def serialize_decimal(self, value):
        return str(value)
    
    @field_serializer("last_update")
    def serialize_date(self, value):
        return str(value)

但是

requests
在序列化时似乎没有使用它。

python json python-requests pydantic pydantic-v2
1个回答
0
投票

这里:

product_item = website_api.Product(**product.__dict__)

如果您的

product_item
是您提到的
Product
模型的实例,那么您应该这样做:

requests.post(url, headers=jwt_auth.auth_header, json=product_item.model_dump())

您不应该需要

datetime.date
Decimal
的序列化器。当我在这个
Product
类上测试这个时,我能够使用
product_item.model_dump()
序列化它,没有任何问题。

就像这里:

import datetime
from decimal import Decimal
from pydantic import BaseModel


class Product(BaseModel):
    id: int
    group_id: int
    sku: str
    price: Decimal
    special_offer_price: Decimal
    last_update: datetime.date


product = Product(
    id=1,
    group_id=1,
    sku="123456",
    price=Decimal("100.00"),
    special_offer_price=Decimal("90.00"),
    last_update=datetime.date(2021, 1, 1),
)

print(product.model_dump())

产生:

{'id': 1, 'group_id': 1, 'sku': '123456', 'price': Decimal('100.00'), 'special_offer_price': Decimal('90.00'), 'last_update': datetime.date(2021, 1, 1)}

或者如果你喜欢它作为 json 字符串,那么这个:

print(product.model_dump_json())

产生:

{"id":1,"group_id":1,"sku":"123456","price":"100.00","special_offer_price":"90.00","last_update":"2021-01-01"}
© www.soinside.com 2019 - 2024. All rights reserved.