为什么Python中的JSON序列化对于datetime对象不能开箱即用?

11 浏览
0 Comments

为什么Python中的JSON序列化对于datetime对象不能开箱即用?

为什么JSON序列化对于datetime对象无法工作?根据我理解的JSON序列化,对于任何对象,基本思路是调用__str__内置函数,然后对得到的对象进行urlencode。但是在datetime对象的情况下,我得到了以下错误:\nTypeError: datetime.datetime(2012, 5, 23, 18, 38, 23, 37566) is not JSON serializable。\n虽然已经存在一种将对象转化为字符串的方式(即__str__),但似乎有意决定不这样做,这是为什么呢?

0
0 Comments

为什么Python中的JSON序列化无法直接处理datetime对象?

问题的出现原因是因为Python的json模块默认情况下无法直接将datetime对象序列化为JSON格式。然而,我们可以通过简单地对json模块进行一行代码的修补来解决这个问题。

解决方法是使用以下代码对json模块进行修补:

import json
import datetime
json.JSONEncoder.default = lambda self,obj: (obj.isoformat() if isinstance(obj, datetime.datetime) else None)

通过将这行代码添加到代码中,我们可以使json模块支持对datetime对象的序列化。修补后的json模块将会将datetime对象转换为isoformat格式。

使用修补后的json模块进行序列化的方式与平常一样,只不过这次datetime对象会被序列化为isoformat格式:

json.dumps({'created':datetime.datetime.now()})

运行上述代码后,我们将得到如下结果:

'{"created": "2015-08-26T14:21:31.853855"}'

如果想要了解更多细节以及一些建议,请参考以下链接:

[StackOverflow: JSON datetime between Python and JavaScript](https://stackoverflow.com/questions/455580/32224522#32224522)

这是我见过的最好的解决方法,只需要一行代码的修补就能解决问题。

0
0 Comments

为什么Python中的datetime对象的JSON序列化不能直接使用?这个问题的出现原因是因为JSON并没有明确指定如何处理日期,所以Python的json库无法决定如何代表日期。这完全取决于其他一方(浏览器、脚本等)在JSON中如何处理日期。

对于默认的序列化,你可能并不关心具体的表示方式。你只需要能够方便地将数据转换成JSON格式并重新转换回来。对于datetime完全无法处理肯定是错误的。

然而,在交换格式中,你需要关心这个问题。Java或JavaScript应用程序中的JSON库如何处理日期?

这时候就需要进行自定义了。默认情况下,如果只是从Python到JSON再到Python,不对常见的数据类型进行默认处理只会增加不必要的开销。另外,其他语言也有标准的JSON转换方式,所以可以从那个标准开始作为一个好的默认方式。

然而,并没有这样的默认方式。标准中并没有指定任何方式。

这导致Python无法编码日期对象吗?其他语言并没有这样的问题。JSON的数据抽象使其更加类型灵活,而不是相反。大多数语言(对于自身来说)选择了一种默认的日期时间字符串编码方式,并且至少能够在语言内部一致地读写日期时间值。Python不仅与外部系统不兼容,甚至两个不同的Python应用程序可能以不同的方式处理日期时间/JSON。

但是这里没有互操作性。Python的哲学包括“拒绝猜测”和“明确优于隐式”。没有标准就没有明智的默认方式,Python在这里拒绝猜测并强制你明确选择一种方式。JSON的大多数用例是与其他“未知”客户端进行通信,即使它们有一个默认的日期时间序列化方式,它们对格式也有“不同的想法”。

选择一个格式并不难,但这不是你需要做的全部。举个例子,让sqlalchemy与嵌套在postgresql JSON列中的包含不同嵌套级别的字典(包含日期时间)一起工作是非平凡的。对于Go、Ruby和JavaScript来说,这只是一个简单的字典/哈希序列化任务。然而Python却无法做到这一点。Python在从字符串创建日期时间方面确实做出了选择,并且还有一些通用标准,所以在这种情况下,“Python的哲学”似乎最多是循环逻辑。

如果json.dumps可以自动编码日期时间,那么json.loads就需要自动解码。因此,JSON字符串始终是Python字符串,除非它们以某种方式格式化,以便json.loads决定它们是日期时间,然后它们才变成日期时间。即使它们一开始只是字符串。

这正是JSON的工作方式。上下文定义了6种JSON类型的含义。没有上下文,字符串只是一个字符串;有了上下文,你就知道你期望的类型是什么。在JSON中,函数对称性并不重要,功能才是最重要的。

0
0 Comments

为什么Python中的datetime对象在JSON序列化时不能直接工作?

JSON模块中的默认编码器`json.JSONEncoder`并不支持直接对datetime对象进行序列化。为了解决这个问题,我们需要扩展`json.JSONEncoder`,并提供自己的`default`方法来序列化对象。

下面是一个示例代码:

import json
import datetime
from time import mktime
class MyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return int(mktime(obj.timetuple()))
        return json.JSONEncoder.default(self, obj)
print json.dumps(obj, cls=MyEncoder)

如其他人正确指出的,问题的原因是JSON的标准并没有规定如何表示日期时间。

在JSON响应中,你将得到一个Unix时间戳。可以参考这个问题来学习如何将Unix时间戳转换为日期时间。

感谢你的建议。我遵循了你的代码,并稍微修改了`isinstance`检查部分,如下所示:

if isinstance(obj, datetime.datetime):
    return obj.strftime('%Y/%m/%d/%H/%M/%S')
elif isinstance(obj, datetime.date):
    return obj.strftime('%Y/%m/%d')

使用`mktime`确实可以工作,但我发现了一种更好的方法。JSON使用ISO 8601格式来表示时间戳。要在Python中获得相同类型的时间格式,只需在datetime对象后面添加`.isoformat()`即可。

0