我有一个十进制('3.9')作为对象的一部分,并希望将其编码为一个JSON字符串,它应该看起来像{'x': 3.9}。我不关心客户端的精度,所以浮点数很好。
有什么好方法来序列化它吗?JSONDecoder不接受Decimal对象,提前转换为浮点数会产生{'x': 3.8999999999999999},这是错误的,而且会浪费大量带宽。
我有一个十进制('3.9')作为对象的一部分,并希望将其编码为一个JSON字符串,它应该看起来像{'x': 3.9}。我不关心客户端的精度,所以浮点数很好。
有什么好方法来序列化它吗?JSONDecoder不接受Decimal对象,提前转换为浮点数会产生{'x': 3.8999999999999999},这是错误的,而且会浪费大量带宽。
当前回答
我尝试在GAE 2.7中从simplejson切换到内置json,在小数方面有问题。如果default返回str(o),则有引号(因为_iterencode对default的结果调用_iterencode), float(o)将删除尾随0。
如果default返回一个继承自float(或任何调用repr而没有额外格式化的对象)的类的对象,并且有自定义__repr__方法,它似乎像我想要的那样工作。
import json
from decimal import Decimal
class fakefloat(float):
def __init__(self, value):
self._value = value
def __repr__(self):
return str(self._value)
def defaultencode(o):
if isinstance(o, Decimal):
# Subclass float with custom repr?
return fakefloat(o)
raise TypeError(repr(o) + " is not JSON serializable")
json.dumps([10.20, "10.20", Decimal('10.20')], default=defaultencode)
'[10.2, "10.20", 10.20]'
其他回答
对于任何想要快速解决的人来说,这里是我如何从Django中的查询中删除Decimal的
total_development_cost_var = process_assumption_objects.values('total_development_cost').aggregate(sum_dev = Sum('total_development_cost', output_field=FloatField()))
total_development_cost_var = list(total_development_cost_var.values())
步骤1:使用,output_field=FloatField()在你的查询 步骤2:使用列表eg list(total_development_cost_var.values())
希望能有所帮助
如果你想传递一个包含小数的字典到请求库(使用json关键字参数),你只需要安装simplejson:
$ pip3 install simplejson
$ python3
>>> import requests
>>> from decimal import Decimal
>>> # This won't error out:
>>> requests.post('https://www.google.com', json={'foo': Decimal('1.23')})
这个问题的原因是,请求只在simplejson存在时才使用它,如果它没有安装,则回落到内置json。
3.9不能准确地在IEEE浮点数中表示,它总是以3.899999999999999999表示,例如,尝试打印repr(3.9),你可以在这里阅读更多信息:
http://en.wikipedia.org/wiki/Floating_point http://docs.sun.com/source/806-3568/ncg_goldberg.html
所以如果你不想要float,唯一的选项你必须将它作为字符串发送,并允许自动将十进制对象转换为JSON,做这样的事情:
import decimal
from django.utils import simplejson
def json_encode_decimal(obj):
if isinstance(obj, decimal.Decimal):
return str(obj)
raise TypeError(repr(obj) + " is not JSON serializable")
d = decimal.Decimal('3.5')
print simplejson.dumps([d], default=json_encode_decimal)
您可以根据需要创建一个自定义JSON编码器。
import json
from datetime import datetime, date
from time import time, struct_time, mktime
import decimal
class CustomJSONEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, datetime):
return str(o)
if isinstance(o, date):
return str(o)
if isinstance(o, decimal.Decimal):
return float(o)
if isinstance(o, struct_time):
return datetime.fromtimestamp(mktime(o))
# Any other serializer if needed
return super(CustomJSONEncoder, self).default(o)
解码器可以这样命名,
import json
from decimal import Decimal
json.dumps({'x': Decimal('3.9')}, cls=CustomJSONEncoder)
输出将是:
>>'{"x": 3.9}'
我将分享flask 2.1.0对我有用的东西 当我创建字典时,必须从jsonify使用我使用四舍五入:
json_dict['price'] = round(self.price, ndigits=2) if self.price else 0
这样我就可以返回D.DD号或0,而不需要使用全局配置。这很好,因为有些十进制坐标需要更大,比如经纬度坐标。
return jsonify(json_dict)