如何将包含复杂对象键的Python字典导出为JSON?
import datetime, json
x = {'alpha': {datetime.date.today(): 'abcde'}}
print json.dumps(x)
上面的代码会出错,出现一个TypeError
,因为JSON对象的键必须是字符串。json.dumps
这个函数有一个叫做default的参数,当JSON对象的值引发TypeError
时会调用这个参数,但似乎没有办法对键做同样的处理。那么,有什么优雅的方法来解决这个问题呢?
6 个回答
你可以这样写:
x = {'alpha': {datetime.date.today().strftime('%d-%m-%Y'): 'abcde'}}
这段代码的意思是,创建一个叫做 x 的变量,它是一个字典。这个字典里面有一个键叫 'alpha',而这个键的值又是一个字典。这个内部字典的键是今天的日期,格式是“日-月-年”,而这个键对应的值是字符串 'abcde'。
你可以看看这个网站:http://jsonpickle.github.io/,它可能正是你需要的。当我遇到类似的问题时,我最后是这样做的:
to_save = jsonpickle.encode(THE_THING, unpicklable=False, max_depth=4, make_refs=False)
你可以扩展 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"}'。为了更好用,可以把它封装成一个函数 :-)