当密钥是非平凡的对象时,如何将Python字典转储到JSON?

ipa*_*ola 9 python json

import datetime, json
x = {'alpha': {datetime.date.today(): 'abcde'}}
print json.dumps(x)
Run Code Online (Sandbox Code Playgroud)

上面的代码失败,TypeError因为JSON对象的键需要是字符串.该json.dumps函数有一个名为default的参数,当JSON对象的引发a 时调用该参数TypeError,但似乎无法为该执行此操作.解决这个问题最优雅的方法是什么?

sup*_*een 5

您可以扩展json.JSONEncoder以创建您自己的编码器,该编码器将能够处理datetime.datetime对象(或您想要的任何类型的对象),从而创建一个可以作为新的datetime.datetime再现的字符串.实例.我相信它应该就像让你的datetime.datetime实例上的json.JSONEncoder调用repr()一样简单.

有关如何执行此操作的过程在json模块文档中进行了描述.

json模块检查它需要编码的每个值的类型,默认情况下它只知道如何处理dicts,lists,tuples,strs,unicode对象,int,long,float,boolean和none :-)

对您来说也很重要的可能是JSONEncoder的skipkeys参数.


阅读完您的评论之后,我得出结论,没有简单的解决方案让JSONEncoder使用自定义函数对字典键进行编码.如果您感兴趣,可以查看源和方法iterencode(),它调用_iterencode(),调用_iterencode_dict(),这是引发类型错误的地方.

最简单的方法是使用isoformatted键创建一个新的dict,如下所示:

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)
Run Code Online (Sandbox Code Playgroud)

返回'{"2010-09-15T23:24:36.169710":"foo","2010-09-15T23:24:36.169723":"bar"}'.对于细节,请将其包装在一个函数中:-)

  • 这仅适用于字典的值,而不适用于键.似乎无法覆盖密钥的编码. (3认同)
  • 那讲得通。但是具有定义此行为的能力会很好。它已经具有您可以覆盖的default()方法。为什么不提供default_key()方法? (2认同)