【问题标题】:JSON dumps Decimal is not serializable [duplicate]JSON转储十进制不可序列化[重复]
【发布时间】:2015-04-24 12:46:48
【问题描述】:

编辑:使用

添加新输出
logging.info(id(type(Decimal(10))))
logging.info(id(type(obj)))

我正在尝试转储到 JSON。我知道我需要将 Decimal 转换为浮点数,所以这是我的代码:

def get(self):
    results = CheckPulseRequest.get(get_args(self.request))
    self.response.headers['Content-Type'] = 'application/json'
    self.response.out.write(json.dumps(results, cls=DateTimeEncoder))

然后我定义了 DateTimeEncoder 如下:

class DateTimeEncoder(json.JSONEncoder):
    logging.info("In DateTimeEncoder Class")

    def default(self, obj):
        logging.info(id(type(Decimal(10))))
        logging.info(id(type(obj)))
        logging.info(type(Decimal(10)))
        logging.info(type(obj))
        logging.info(isinstance(Decimal(10), (int, long, float, complex, Decimal)))
        logging.info(isinstance(obj, (int, long, float, complex, Decimal)))

        if isinstance(obj, Decimal):
            logging.info("Is Instance of Decimal")
            return float(obj)
        elif hasattr(obj, 'isoformat'):
            logging.info("Is ISO Format")
            return obj.isoformat()
        else:
            logging.info("Else")
            return json.JSONEncoder.default(self, obj)

我得到以下日志输出。我的十进制对象不会转换为浮点数。请注意,该对象与 Decimal 具有相同的类型,但 isinstance 测试仅在 Decimal(10) 测试中为 True。我错过了什么?

INFO     2015-02-23 18:49:45,737 check_pulse_request.py:25] Getting Check Pulse Request ID: 4
INFO     2015-02-23 18:49:46,374 main.py:179] 140647859901984
INFO     2015-02-23 18:49:46,375 main.py:180] 140647856664608
INFO     2015-02-23 18:49:46,375 main.py:181] <class 'decimal.Decimal'>
INFO     2015-02-23 18:49:46,375 main.py:182] <class 'decimal.Decimal'>
INFO     2015-02-23 18:49:46,375 main.py:183] True
INFO     2015-02-23 18:49:46,375 main.py:184] False
INFO     2015-02-23 18:49:46,376 main.py:193] Else
ERROR    2015-02-23 18:49:46,376 webapp2.py:1552] Decimal('-122.39906660000000') is not JSON serializable
Traceback (most recent call last):
  File "/Users/sheridangray/Projects/adt-bundle-mac-x86_64-20140702/sdk/google-cloud-sdk/platform/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1535, in __call__
    rv = self.handle_exception(request, response, e)
  File "/Users/sheridangray/Projects/adt-bundle-mac-x86_64-20140702/sdk/google-cloud-sdk/platform/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1529, in __call__
    rv = self.router.dispatch(request, response)
  File "/Users/sheridangray/Projects/adt-bundle-mac-x86_64-20140702/sdk/google-cloud-sdk/platform/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)
  File "/Users/sheridangray/Projects/adt-bundle-mac-x86_64-20140702/sdk/google-cloud-sdk/platform/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "/Users/sheridangray/Projects/adt-bundle-mac-x86_64-20140702/sdk/google-cloud-sdk/platform/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "/Users/sheridangray/Projects/adt-bundle-mac-x86_64-20140702/sdk/google-cloud-sdk/platform/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "/Users/sheridangray/Projects/city-pulse-appengine/city-pulse/main.py", line 38, in get
    self.response.out.write(json.dumps(results, cls=DateTimeEncoder))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 250, in dumps
    sort_keys=sort_keys, **kw).encode(obj)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
  File "/Users/sheridangray/Projects/city-pulse-appengine/city-pulse/main.py", line 194, in default
    return json.JSONEncoder.default(self, obj)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: Decimal('-122.39906660000000') is not JSON serializable

【问题讨论】:

  • 您的代码中没有任何其他名为 Decimal 的类吗?
  • Hrm,不知道为什么这被否决了。有代码,有错误信息,有什么不喜欢的?当然,错误看起来不协调,但显然这里存在类型不匹配,因为type(obj) 使它看起来decimal.Decimal() 实例。我只是不确定default 代码中的Decimal 是否与传入的类相同。两个不同的decimal.Decimal 类可以解释错误。
  • 您能否将id(Decimal)id(type(obj)) 的日志记录添加到您的代码中并重新运行?
  • 我会小心地将小数序列化为浮点数,因为你可能会失去精度——因为浮点数只有一组有限的值,而 Decimal 的值是无限的。仅当您的值具有 20 个或更多有效数字时,这才真正重要。考虑使用simplejson 使用simplejson.dumps(obj, use_decimal=True)
  • @Dunes:所有simplejson 所做的都是使用str(Decimal)。 OP 可以在这里简单地做同样的事情。

标签: python json serialization


【解决方案1】:

我并没有真正“解决”这个问题,而是通过将我的 MySQL 数据库列更改为 FLOAT 来解决这个问题。

【讨论】:

  • 如果精度很重要(例如货币等),您可能不想使用float
  • 在这种情况下,精度并不是非常重要,因为它首先是一个近似值:)
猜你喜欢
  • 2023-03-23
  • 2020-12-07
  • 1970-01-01
  • 1970-01-01
  • 2011-04-30
  • 2013-06-13
  • 2017-12-30
  • 1970-01-01
  • 2019-01-27
相关资源
最近更新 更多