我有一个十进制('3.9')作为对象的一部分,并希望将其编码为一个JSON字符串,它应该看起来像{'x': 3.9}。我不关心客户端的精度,所以浮点数很好。

有什么好方法来序列化它吗?JSONDecoder不接受Decimal对象,提前转换为浮点数会产生{'x': 3.8999999999999999},这是错误的,而且会浪费大量带宽。


当前回答

我将分享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)

其他回答

对于Django用户:

最近遇到TypeError: Decimal('2337.00')不是JSON可序列化的 当JSON编码时,即JSON .dump (data)

解决方案:

# converts Decimal, Datetime, UUIDs to str for Encoding
from django.core.serializers.json import DjangoJSONEncoder  

json.dumps(response.data, cls=DjangoJSONEncoder)

但是,现在Decimal值将是一个字符串,现在我们可以在解码数据时显式设置Decimal /float值解析器,使用json.loads中的parse_float选项:

import decimal 

data = json.loads(data, parse_float=decimal.Decimal) # default is float(num_str)

我尝试在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]'

在我的Flask应用程序中,它使用python 2.7.11, Flask alchemy(具有'db.decimal'类型)和Flask Marshmallow(用于'即时'序列化器和反序列化器),我有这个错误,每次我做GET或POST。序列化器和反序列化器未能将十进制类型转换为任何可识别的JSON格式。

然后,我做了一个“pip install simplejson” 只要加上

import simplejson as json

序列化器和反序列化器又开始工作了。我什么也没做…… 十进制显示为'234.00'浮点格式。

对于任何想要快速解决的人来说,这里是我如何从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.JSONEncoder怎么样?

class DecimalEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, decimal.Decimal):
            # wanted a simple yield str(o) in the next line,
            # but that would mean a yield on the line with super(...),
            # which wouldn't work (see my comment below), so...
            return (str(o) for o in [o])
        return super(DecimalEncoder, self).default(o)

然后像这样使用它:

json.dumps({'x': decimal.Decimal('5.5')}, cls=DecimalEncoder)