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

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


当前回答

原生Django选项缺失了,所以我将为下一个寻找它的guy/gall添加它。

从Django 1.7开始。x中有一个内置的DjangoJSONEncoder,你可以从django.core. serialzers .json中获取。

import json
from django.core.serializers.json import DjangoJSONEncoder
from django.forms.models import model_to_dict

model_instance = YourModel.object.first()
model_dict = model_to_dict(model_instance)

json.dumps(model_dict, cls=DjangoJSONEncoder)

很快!

其他回答

您可以根据需要创建一个自定义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}'

我只有美元!

我扩展了一堆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'浮点格式。

我的2美分简单的解决方案,如果你确定Decimal是你的json dumps方法中唯一的坏人:

print(json.loads(json.dumps({
    'a': Decimal(1230),
    'b': Decimal(11111111123.22),
}, default=lambda x: eval(str(x)))))

>>> {'a': 1230, 'b': 11111111123.22}

这里“聪明”的事情是使用default将Decimal自动转换为int或float,利用eval函数:

但是在你的代码上使用eval时一定要小心,因为这可能会导致安全问题;)

原生Django选项缺失了,所以我将为下一个寻找它的guy/gall添加它。

从Django 1.7开始。x中有一个内置的DjangoJSONEncoder,你可以从django.core. serialzers .json中获取。

import json
from django.core.serializers.json import DjangoJSONEncoder
from django.forms.models import model_to_dict

model_instance = YourModel.object.first()
model_dict = model_to_dict(model_instance)

json.dumps(model_dict, cls=DjangoJSONEncoder)

很快!