如何将包含复杂对象键的Python字典导出为JSON?

14 投票
6 回答
14360 浏览
提问于 2025-04-16 04:11
import datetime, json
x = {'alpha': {datetime.date.today(): 'abcde'}}
print json.dumps(x)

上面的代码会出错,出现一个TypeError,因为JSON对象的键必须是字符串。json.dumps这个函数有一个叫做default的参数,当JSON对象的引发TypeError时会调用这个参数,但似乎没有办法对做同样的处理。那么,有什么优雅的方法来解决这个问题呢?

6 个回答

0

你可以这样写:

x = {'alpha': {datetime.date.today().strftime('%d-%m-%Y'): 'abcde'}}

这段代码的意思是,创建一个叫做 x 的变量,它是一个字典。这个字典里面有一个键叫 'alpha',而这个键的值又是一个字典。这个内部字典的键是今天的日期,格式是“日-月-年”,而这个键对应的值是字符串 'abcde'。

2

你可以看看这个网站:http://jsonpickle.github.io/,它可能正是你需要的。当我遇到类似的问题时,我最后是这样做的:

to_save = jsonpickle.encode(THE_THING, unpicklable=False, max_depth=4, make_refs=False)
6

你可以扩展 json.JSONEncoder 来创建你自己的编码器,这样就能处理 datetime.datetime 对象(或者你想处理的任何类型的对象),并生成一个字符串,这个字符串可以用来重新创建一个新的 datetime.datetime 实例。我认为这应该很简单,只需要让 json.JSONEncoder 对你的 datetime.datetime 实例调用 repr() 方法就行了。

具体的操作步骤可以在 json 模块文档 中找到。

json 模块会检查它需要编码的每个值的类型,默认情况下,它只知道如何处理字典、列表、元组、字符串、unicode 对象、整数、长整型、浮点数、布尔值和 None :-)

另外,JSONEncoder 的 skipkeys 参数对你来说也可能很重要。


在阅读了你的评论后,我得出结论,想要让 JSONEncoder 用自定义函数编码字典的键并没有简单的解决方案。如果你感兴趣,可以查看源代码和 iterencode() 方法,它会调用 _iterencode(),然后再调用 _iterencode_dict(),错误就是在这里抛出的。

对你来说,最简单的方法是创建一个新的字典,使用 ISO 格式的键,像这样:

import datetime, json

D = {datetime.datetime.now(): 'foo',
     datetime.datetime.now(): 'bar'}

new_D = {}

for k,v in D.iteritems():
  new_D[k.isoformat()] = v

json.dumps(new_D)

这会返回 '{"2010-09-15T23:24:36.169710": "foo", "2010-09-15T23:24:36.169723": "bar"}'。为了更好用,可以把它封装成一个函数 :-)

撰写回答