I want to json.dump()
a dictionary that has keys of datetime.date
type, and to do so I made a serializer class to encode the date
keys as strings. To my surprise it works with json.dumps()
, but throws an error with json.dump()
. At the end I was able to dump using a workaround, but I'd like to understand what happens here: why does the serializer class work with json.dumps()
and does not work with json.dump()
?
I tried writing a similar function to use with default=
instead of cls=
, tried rewriting this back and forth, tried to adapt some examples I found in the web, but I always ended up with the same error. I don't know what I'm missing here, even after reading the docs. Please enlighten me what do I need to change here to be able to serialize the dates and dump the dictionary.
Here is the MRE (Python 3.8.6):
import json
import datetime
class JSONSerializer(json.JSONEncoder):
@staticmethod
def convert_if_date(_date):
if isinstance(_date, datetime.date):
return _date.strftime('%Y-%m-%d')
return _date
def date_insensitive_encode(self, obj):
if isinstance(obj, dict):
return {self.convert_if_date(k): v for k, v in obj.items()}
return obj
def encode(self, obj):
return super(JSONSerializer, self).encode(
self.date_insensitive_encode(obj))
test_dict = {datetime.date(2022, 7, 10): 'OK'}
print(json.dumps(test_dict, cls=JSONSerializer))
# this prints: {"2022-07-11": "OK"}
with open('dump.json', 'w') as w:
json.dump(test_dict, w, cls=JSONSerializer)
# but this throws a TypeError
Full error:
Traceback (most recent call last):
File "E:/Progz/Python/AppKH/datacontrol/so_mre.py", line 28, in <module>
json.dump(test_dict, w, cls=JSONSerializer)
File "C:\Program Files\Python38\lib\json\__init__.py", line 179, in dump
for chunk in iterable:
File "C:\Program Files\Python38\lib\json\encoder.py", line 431, in _iterencode
yield from _iterencode_dict(o, _current_indent_level)
File "C:\Program Files\Python38\lib\json\encoder.py", line 376, in _iterencode_dict
raise TypeError(f'keys must be str, int, float, bool or None, '
TypeError: keys must be str, int, float, bool or None, not date