如何用Python标准库将Decimal编码为精确的JSON数字?
仅用Python标准库实现Decimal到JSON精确数字的序列化
在Python标准库json模块中,直接将Decimal转为float会丢失精度,转为字符串则会带上引号,无法得到精确的JSON数字格式。以下是仅依赖标准库的可靠实现方案:
安全实现方案(推荐)
通过给Decimal值添加唯一标记,避免误替换普通字符串,最终还原为精确的JSON数字:
import json import re from decimal import Decimal class PreciseDecimalEncoder(json.JSONEncoder): def encode(self, obj): # 遍历对象,给Decimal值添加唯一标记 def traverse(o): if isinstance(o, Decimal): return f"__DECIMAL_MARKER__{str(o)}" elif isinstance(o, dict): return {k: traverse(v) for k, v in o.items()} elif isinstance(o, (list, tuple)): return [traverse(i) for i in o] else: return o # 生成带标记的JSON字符串,再替换标记还原为数字 processed_obj = traverse(obj) json_str = super().encode(processed_obj) json_str = re.sub(r'"__DECIMAL_MARKER__(.*?)"', r'\1', json_str) return json_str # 测试示例 obj = { 'decimal': Decimal("123456789012345.99"), 'regular_string': "12345.99", 'nested': {'value': Decimal("98765.43")} } result = json.dumps(obj, cls=PreciseDecimalEncoder) print(result) # 输出: {"decimal": 123456789012345.99, "regular_string": "12345.99", "nested": {"value": 98765.43}}
方案说明
- 特殊标记
__DECIMAL_MARKER__确保仅替换原本是Decimal的值,不会误改内容为数字的普通字符串。 - 支持嵌套的字典、列表/元组结构中的
Decimal值处理。
简洁实现方案(有局限)
如果能确保业务中没有内容与Decimal字符串表示完全一致的普通字符串,可直接替换数字格式的引号,但存在误替换风险:
import json import re from decimal import Decimal class SimpleDecimalEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, Decimal): return str(obj) return super().default(obj) obj = {'decimal': Decimal("123456789012345.99")} json_str = json.dumps(obj, cls=SimpleDecimalEncoder) json_str = re.sub(r'"(\d+\.?\d*)"', r'\1', json_str) print(json_str) # 输出: {"decimal": 123456789012345.99}
内容的提问来源于stack exchange,提问作者dimmaq
相关产品推荐
相关产品推荐

