我使用Python2.6中的标准json module来序列化浮点数列表。然而,我得到了这样的结果:
>>> import json
>>> json.dumps([23.67, 23.97, 23.87])
'[23.670000000000002, 23.969999999999999, 23.870000000000001]'
我希望浮点数的格式只有两个十进制数字。输出应如下所示:
>>> json.dumps([23.67, 23.97, 23.87])
'[23.67, 23.97, 23.87]'
我试着定义我自己的JSON编码器类:
class MyEncoder(json.JSONEncoder):
def encode(self, obj):
if isinstance(obj, float):
return format(obj, '.2f')
return json.JSONEncoder.encode(self, obj)
这适用于唯一的浮动对象:
>>> json.dumps(23.67, cls=MyEncoder)
'23.67'
但对于嵌套对象则失败:
>>> json.dumps([23.67, 23.97, 23.87])
'[23.670000000000002, 23.969999999999999, 23.870000000000001]'
我不想有外部依赖,所以我更喜欢坚持使用标准的json模块。
我如何才能做到这一点?
发布于 2009-11-14 11:16:28
import simplejson
class PrettyFloat(float):
def __repr__(self):
return '%.15g' % self
def pretty_floats(obj):
if isinstance(obj, float):
return PrettyFloat(obj)
elif isinstance(obj, dict):
return dict((k, pretty_floats(v)) for k, v in obj.items())
elif isinstance(obj, (list, tuple)):
return list(map(pretty_floats, obj))
return obj
print(simplejson.dumps(pretty_floats([23.67, 23.97, 23.87])))
发射
[23.67, 23.97, 23.87]
没有必要使用monkeypatching。
发布于 2015-03-16 05:30:42
非常不幸的是,dumps
不允许你对浮点数做任何事情。然而,loads
做到了。因此,如果您不介意额外的CPU负载,您可以通过编码器/解码器/编码器抛出它,并获得正确的结果:
>>> json.dumps(json.loads(json.dumps([.333333333333, .432432]), parse_float=lambda x: round(float(x), 3)))
'[0.333, 0.432]'
发布于 2011-04-07 07:29:37
如果您使用的是Python 2.7,一个简单的解决方案就是将浮点数显式舍入到所需的精度。
>>> sys.version
'2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)]'
>>> json.dumps(1.0/3.0)
'0.3333333333333333'
>>> json.dumps(round(1.0/3.0, 2))
'0.33'
这是因为Python2.7生成了float rounding more consistent。不幸的是,这在Python 2.6中不起作用:
>>> sys.version
'2.6.6 (r266:84292, Dec 27 2010, 00:02:40) \n[GCC 4.4.5]'
>>> json.dumps(round(1.0/3.0, 2))
'0.33000000000000002'
上面提到的解决方案是2.6的变通方法,但没有一个是完全足够的。如果您的Python运行时使用C版本的json.encoder.FLOAT_REPR模块,则Monkey JSON不起作用。Tom Wuttke答案中的PrettyFloat类可以工作,但前提是%g编码对您的应用程序全局有效。%.15g有点神奇,它之所以有效,是因为浮点精度是17位有效数字,并且%g不打印尾随零。
我花了一些时间尝试制作一个PrettyFloat,允许自定义每个数字的精度。例如,语法类似于
>>> json.dumps(PrettyFloat(1.0 / 3.0, 4))
'0.3333'
要做到这一点并不容易。从float继承是很笨拙的。从Object继承并使用带有自己的JSONEncoder ()方法的default子类应该是可行的,除了json模块似乎假定所有自定义类型都应该序列化为字符串。即:在输出中最终得到Javascript字符串" 0.33“,而不是数字0.33。也许有一种方法可以让它工作,但它比看起来更难。
https://stackoverflow.com/questions/1447287
复制相似问题