[英]Python 3.5 JSON serialize a Decimal object
I need to encode into json a decimal value: 999999.99990000005
while not losing precision and not changing representation to string.我需要将十进制值编码到 json 中:
999999.99990000005
,同时不丢失精度并且不将表示更改为字符串。 Expecting { "prc": 999999.99990000005 }
期待
{ "prc": 999999.99990000005 }
From [this post][1] i have this code.从 [this post][1] 我有这个代码。
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')}
but it produces a string但它会产生一个字符串
json.dumps(y, cls=DecimalEncoder)
'{"cPrc": "999999.99990000005"}'
replacing str(o)
with float(o)
in isinstance
truncates the number.在
isinstance
中用float(o)
替换str(o)
会截断数字。 Any way to get the non-string result?有什么方法可以获得非字符串结果? PS I cannot use any external modules like simplejson.
PS 我不能使用任何像 simplejson 这样的外部模块。
EDIT: If I keep the value as a string, following produces a string too.编辑:如果我将值保留为字符串,则以下也会产生一个字符串。
>>> x = json.loads("""{ "cPrc" : "999999.99990000005" }""", parse_float=decimal.Decimal)
>>> x
{'cPrc': '999999.99990000005'}
It is not the most pretty but if you insist on using json we can create a custom decoder and have our encoder specify the type when handling decimal data. 它不是最漂亮的但是如果你坚持使用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)
The code above adds the decimal type as a flag for our decoder as well as encoding the decimal as a string to keep precision. 上面的代码将十进制类型添加为解码器的标志,并将十进制编码为字符串以保持精度。
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
The decoder checks for our decimal type flag and if so uses the decimal constructor. 解码器检查我们的十进制类型标志,如果是,则使用十进制构造函数。 For all other instances it uses default decoding
对于所有其他实例,它使用默认解码
input = { 'prc' : decimal.Decimal('999999.99990000005')}
encoded = json.dumps(input, cls=DecimalEncoder)
decoded = json.loads(encoded, cls=DecimalDecoder)
The final result should take our input, encode it, and decode the result as a decimal object. 最终结果应该接受我们的输入,对其进行编码,并将结果解码为十进制对象。
Answering my own question. 回答我自己的问题。 I output Decimal objects surrounded by special character `.
我输出由特殊字符`包围的十进制对象。 Then remove it and the double-quote from text.
然后从文本中删除它和双引号。
class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
return '`'+str(o)+'`' #` is special, will be removed later
return super(DecimalEncoder, self).default(o)
json.dumps(y, cls=DecimalEncoder).replace("\"`",'').replace("`\"",'')
From version 3.1 json library supports parse_float option that allows enconding/deconding as Decimal.从 3.1 版开始, json库支持parse_float选项,该选项允许将编码/解码为十进制。
Refer to official documentation for usage examples.使用示例请参考官方文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.