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

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


当前回答

我只有美元!

我扩展了一堆JSON编码器,因为我正在为我的web服务器序列化大量数据。这里有一些不错的代码。请注意,它可以很容易地扩展到几乎任何你想要的数据格式,并将3.9再现为“thing”:3.9

JSONEncoder_olddefault = json.JSONEncoder.default
def JSONEncoder_newdefault(self, o):
    if isinstance(o, UUID): return str(o)
    if isinstance(o, datetime): return str(o)
    if isinstance(o, time.struct_time): return datetime.fromtimestamp(time.mktime(o))
    if isinstance(o, decimal.Decimal): return str(o)
    return JSONEncoder_olddefault(self, o)
json.JSONEncoder.default = JSONEncoder_newdefault

让我的生活轻松多了…

其他回答

在我的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编码器,因为我正在为我的web服务器序列化大量数据。这里有一些不错的代码。请注意,它可以很容易地扩展到几乎任何你想要的数据格式,并将3.9再现为“thing”:3.9

JSONEncoder_olddefault = json.JSONEncoder.default
def JSONEncoder_newdefault(self, o):
    if isinstance(o, UUID): return str(o)
    if isinstance(o, datetime): return str(o)
    if isinstance(o, time.struct_time): return datetime.fromtimestamp(time.mktime(o))
    if isinstance(o, decimal.Decimal): return str(o)
    return JSONEncoder_olddefault(self, o)
json.JSONEncoder.default = JSONEncoder_newdefault

让我的生活轻松多了…

十进制不适合通过以下方式进行转换:

浮子由于精度问题 由于openapi的限制

我们仍然需要直接十进制到一个数字json序列化。

下面是@tesdal的fakfloat解决方案的扩展(在v3.5.2rc1中关闭)。 它使用fakestr + monkeypatching来避免引号和小数的“浮动”。

import json.encoder
from decimal import Decimal


def encode_fakestr(func):
    def wrap(s):
        if isinstance(s, fakestr):
            return repr(s)
        return func(s)
    return wrap


json.encoder.encode_basestring = encode_fakestr(json.encoder.encode_basestring)
json.encoder.encode_basestring_ascii = encode_fakestr(json.encoder.encode_basestring_ascii)


class fakestr(str):
    def __init__(self, value):
        self._value = value
    def __repr__(self):
        return str(self._value)


class DecimalJsonEncoder(json.encoder.JSONEncoder):
    def default(self, o):
        if isinstance(o, Decimal):
            return fakestr(o)
        return super().default(o)


json.dumps([Decimal('1.1')], cls=DecimalJsonEncoder)

[1.1]

我不明白为什么python开发人员强迫我们在不适合使用浮点数的地方使用浮点数。

这个问题很老了,但是对于大多数用例,Python3中似乎有一个更好、更简单的解决方案:

number = Decimal(0.55)
converted_number = float(number) # Returns: 0.55 (as type float)

你可以把Decimal转换成float。