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

时间:2010-09-15 20:04:11

标签: python json

import datetime, json
x = {'alpha': {datetime.date.today(): 'abcde'}}
print json.dumps(x)

由于JSON对象的键需要是字符串,因此上面的代码失败并带有TypeErrorjson.dumps函数有一个名为default的参数,当JSON对象的引发TypeError时会调用该参数,但似乎没有办法为< EM>键的。解决这个问题最优雅的方法是什么?

4 个答案:

答案 0 :(得分:5)

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

json module docs

中介绍了如何执行此操作的步骤

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)

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

答案 1 :(得分:2)

http://jsonpickle.github.io/可能就是你想要的。面对类似问题时,我最终做了:

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

如果您确实需要这样做,可以对json.encoder进行猴子补丁:

from _json import encode_basestring_ascii  # used when ensure_ascii=True (which is the default where you want everything to be ascii)
from _json import encode_basestring  # used in any other case

def _patched_encode_basestring(o):
    """
    Monkey-patching Python's json serializer so it can serialize keys that are not string!
    You can monkey patch the ascii one the same way.
    """
    if isinstance(o, MyClass):
        return my_serialize(o)
    return encode_basestring(o)


json.encoder.encode_basestring = _patched_encode_basestring