You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python标准json库序列化含Decimal的dataclass?

解决Dataclass含Decimal字段的JSON序列化问题

你遇到的问题核心是:自定义的JSONEncoder只处理了Decimal类型,但**TransactionData实例本身不属于JSON原生可序列化类型**,所以需要同时处理dataclass实例和Decimal的序列化逻辑。以下是两种基于标准json库的可行方案:

方案一:先转字典再用自定义Encoder

先通过dataclasses.asdict()把dataclass实例转为普通字典,再用自定义Encoder处理字典里的Decimal字段:

from dataclasses import dataclass, asdict
import json
from decimal import Decimal

@dataclass
class TransactionData:
    amount: Decimal
    description: str

# 自定义Encoder处理Decimal
class DecimalEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Decimal):
            # 金融场景推荐转字符串保留精度,也可按需转float:return float(obj)
            return str(obj)
        return super().default(obj)

# 实例化并序列化
tx = TransactionData(amount=Decimal('123.45'), description="超市采购")
json_result = json.dumps(asdict(tx), cls=DecimalEncoder)
print(json_result)
# 输出:{"amount": "123.45", "description": "超市采购"}

方案二:在自定义Encoder中同时处理Dataclass

如果不想每次手动调用asdict(),可以在Encoder里直接识别dataclass实例并自动转字典:

from dataclasses import dataclass, is_dataclass, asdict
import json
from decimal import Decimal

@dataclass
class TransactionData:
    amount: Decimal
    description: str

class CustomJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        # 先处理dataclass实例
        if is_dataclass(obj):
            return asdict(obj)
        # 再处理Decimal
        if isinstance(obj, Decimal):
            return str(obj)
        # 其他类型交给父类处理
        return super().default(obj)

# 直接序列化dataclass实例
tx = TransactionData(amount=Decimal('678.90'), description="房租")
json_result = json.dumps(tx, cls=CustomJSONEncoder)
print(json_result)
# 输出:{"amount": "678.90", "description": "房租"}

关键说明

  • 之前报错的原因:json.dumps()默认只认识JSON原生类型(字符串、数字、列表、字典等),dataclass实例不属于这些类型,所以即使处理了Decimal,依然会报错。
  • Decimal转字符串是为了避免浮点数精度丢失,若业务场景允许精度损失,也可以改为return float(obj)。

内容的提问来源于stack exchange,提问作者clattenburg cake

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 12:24:45