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)
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
def _tuple_to_string(obj: Any) -> Any:
"""Serialize tuple-keys to string representation. A tuple wil be obtain a leading '__tuple__' string and decomposed in list representation.
Args:
obj (Any): Typically a dict, tuple, list, int, or string.
Returns:
Any: Input object with serialized tuples.
"""
# deep copy object to avoid manipulation during iteration
obj_copy = copy.deepcopy(obj)
# if the object is a dictionary
if isinstance(obj, dict):
# iterate over every key
for key in obj:
# set for later to avoid modification in later iterations when this var does not get overwritten
serialized_key = None
# if key is tuple
if isinstance(key, tuple):
# stringify the key
serialized_key = f"__tuple__{list(key)}"
# replace old key with encoded key
obj_copy[serialized_key] = obj_copy.pop(key)
# if the key was modified
if serialized_key is not None:
# do it again for the next nested dictionary
obj_copy[serialized_key] = _tuple_to_string(obj[key])
# else, just do it for the next dictionary
else:
obj_copy[key] = _tuple_to_string(obj[key])
return obj_copy
def _string_to_tuple(obj: Any) -> Any:
"""Convert serialized tuples back to original representation. Tuples need to have a leading "__tuple__" string.
Args:
obj (Any): Typically a dict, tuple, list, int, or string.
Returns:
Any: Input object with recovered tuples.
"""
# deep copy object to avoid manipulation during iteration
obj_copy = copy.deepcopy(obj)
# if the object is a dictionary
if isinstance(obj, dict):
# iterate over every key
for key in obj:
# set for later to avoid modification in later iterations when this var does not get overwritten
serialized_key = None
# if key is a serialized tuple starting with the "__tuple__" affix
if isinstance(key, str) and key.startswith("__tuple__"):
# decode it so tuple
serialized_key = tuple(key.split("__tuple__")[1].strip("[]").replace("'", "").split(", "))
# if key is number in string representation
if all(entry.isdigit() for entry in serialized_key):
# convert to integer
serialized_key = tuple(map(int, serialized_key))
# replace old key with encoded key
obj_copy[serialized_key] = obj_copy.pop(key)
# if the key was modified
if serialized_key is not None:
# do it again for the next nested dictionary
obj_copy[serialized_key] = _string_to_tuple(obj[key])
# else, just do it for the next dictionary
else:
obj_copy[key] = _string_to_tuple(obj[key])
# if another instance was found
elif isinstance(obj, list):
for item in obj:
_string_to_tuple(item)
return obj_copy
插入用于对示例进行编码/解码的自定义逻辑,方法是更改
if isinstance(key, tuple):
# stringify the key
serialized_key = f"__tuple__{list(key)}"
if isinstance(key, str) and key.startswith("__tuple__"):
# decode it so tuple
serialized_key = tuple(key.split("__tuple__")[1].strip("[]").replace("'", "").split(", "))
# if key is number in string representation
if all(entry.isdigit() for entry in serialized_key):
# convert to integer
serialized_key = tuple(map(int, serialized_key))
5条答案
按热度按时间xqk2d5yq1#
你可以扩展json.JSONEncoder来创建你自己的编码器,它将能够处理datetime.datetime对象(或者你想要的任何类型的对象),这样就可以创建一个字符串,这个字符串可以被复制为一个新的datetime.datetime示例。我相信这应该和让json.JSONEncoder在你的datetime.datetime示例上调用repr()一样简单。
json模块文档中描述了如何执行此操作的过程。
json模块检查它需要编码的每个值的类型,默认情况下,它只知道如何处理dict、list、tuple、strs、unicode对象、int、long、float、boolean和none:-)
JSONEncoder的skipkeys参数对您来说也很重要。
在阅读了您的评论之后,我得出结论,让JSONEncoder使用自定义函数对字典的键进行编码并不是一个简单的解决方案。如果您感兴趣,可以查看源代码和方法iterencode(),该方法调用_iterencode(),该方法调用_iterencode_dict(),这是引发类型错误的地方。
对你来说最简单的方法是用等格式键创建一个新的dict,如下所示:
返回“{“2010-09- 15 T23:24:36.169710”:“foo”,“2010年9月15日23:24:36.169723”:“bar”}“。为了精确起见,请将其 Package 在函数中:-)
r7s23pms2#
http://jsonpickle.github.io/可能是你想要的,当面临类似的问题时,我最终做了:
zqdjd7g93#
你可以做
x = {'alpha': {datetime.date.today().strftime('%d-%m-%Y'): 'abcde'}}
nkkqxpd94#
如果你真的需要这样做,你可以monkeypatch json.encoder:
rsaldnfx5#
JSON只接受这里提到的数据类型进行编码。正如@supakeen提到的,你可以扩展JSONEncoder类,以便对字典中的任何值进行编码,但不对键进行编码!如果你想对键进行编码,你必须自己做。
我使用了一个递归函数,以便将元组键编码为字符串,并在以后恢复它们。
下面是一个例子:
这会将
("blah", "blub")
的元组转换为"__tuple__["blah", "blub"]"
,这样你就可以使用json.dumps()
或json.dump()
来转储它,你可以在解码过程中使用前导"__tuple"__
来检测它们,因此,我使用了这个函数:插入用于对示例进行编码/解码的自定义逻辑,方法是更改
分别在
_tuple_to_string
函数或来自_string_to_tuple
函数的对应代码块中:然后,您可以像往常一样使用它:
希望我能帮你!