Python JSON序列化十进制对象

2024-04-25 14:19:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个Decimal('3.9')作为对象的一部分,并希望将其编码为一个JSON字符串,该字符串应该类似于{'x': 3.9}。我不在乎客户端的精度,所以浮动就可以了。

有没有好的方法来序列化这个?JSONDecoder不接受十进制对象,并且预先转换为float会产生{'x': 3.8999999999999999}这是错误的,并且会极大地浪费带宽。


Tags: 对象方法字符串json客户端编码序列化错误
3条回答

Simplejson 2.1及更高版本对十进制类型具有本机支持:

>>> json.dumps(Decimal('3.9'), use_decimal=True)
'3.9'

请注意,use_decimal默认为True

def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
    allow_nan=True, cls=None, indent=None, separators=None,
    encoding='utf-8', default=None, use_decimal=True,
    namedtuple_as_object=True, tuple_as_array=True,
    bigint_as_string=False, sort_keys=False, item_sort_key=None,
    for_json=False, ignore_nan=False, **kw):

所以:

>>> json.dumps(Decimal('3.9'))
'3.9'

希望这个特性将包含在标准库中。

我想让大家知道,我在运行Python 2.6.5的web服务器上尝试了MichałMarczyk的答案,它运行得很好。但是,我升级到了python2.7,它停止了工作。我试着想出一种编码十进制对象的方法,这就是我想到的:

import decimal

class DecimalEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, decimal.Decimal):
            return float(o)
        return super(DecimalEncoder, self).default(o)

希望这能帮助那些对Python2.7有问题的人。我测试过了,看起来效果不错。如果有人发现我的解决方案中有任何错误或想出更好的方法,请告诉我。

子类化json.JSONEncoder怎么样?

class DecimalEncoder(json.JSONEncoder):
    def _iterencode(self, o, markers=None):
        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)._iterencode(o, markers)

然后像这样使用它:

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

相关问题 更多 >