我需要将一个十进制值编码为json:999999.99990000005
,同时不丢失精度,也不将表示形式更改为字符串。期望{ "prc" : 999999.99990000005 }
我有这个密码。
import json
import decimal
class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
return str(o)
return super(DecimalEncoder, self).default(o)
y = { 'prc' : decimal.Decimal('999999.99990000005')}
但它会产生一个字符串
json.dumps(y, cls=DecimalEncoder)
'{"cPrc": "999999.99990000005"}'
将
str(o)
替换为float(o)
将截断该数字。有没有办法得到非字符串结果?
P.S.I不能使用任何外部模块,如simplejson。
编辑:
如果将值保留为字符串,则following也会生成字符串。
>>> x = json.loads("""{ "cPrc" : "999999.99990000005" }""", parse_float=decimal.Decimal)
>>> x
{'cPrc': '999999.99990000005'}
最佳答案
它不是最漂亮的,但是如果你坚持使用json,我们可以创建一个自定义解码器,并让我们的编码器在处理十进制数据时指定类型。
class DecimalEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, decimal.Decimal):
return {
"_type": "decimal",
"value": str(obj)
}
return super(DecimalEncoder, self).default(obj)
上面的代码添加十进制类型作为解码器的标志,并将十进制编码为字符串以保持精度。
class DecimalDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
def object_hook(self, obj):
if '_type' not in obj:
return obj
type = obj['_type']
if type == 'decimal':
return decimal.Decimal(obj['value'])
return obj
解码器检查十进制类型标志,如果是,则使用十进制构造函数。对于所有其他情况,它使用默认解码
input = { 'prc' : decimal.Decimal('999999.99990000005')}
encoded = json.dumps(input, cls=DecimalEncoder)
decoded = json.loads(encoded, cls=DecimalDecoder)
最终结果应该接受我们的输入,对其进行编码,并将结果解码为十进制对象。