Как выгрузить словарь Python в JSON, когда ключи являются нетривиальными объектами? - PullRequest
8 голосов
/ 16 сентября 2010
import datetime, json
x = {'alpha': {datetime.date.today(): 'abcde'}}
print json.dumps(x)

Приведенный выше код завершается с TypeError, поскольку ключи объектов JSON должны быть строками. Функция json.dumps имеет параметр по умолчанию, который вызывается, когда значение объекта JSON поднимает TypeError, но, похоже, для этого нет ключа key . Какой самый элегантный способ обойти это?

Ответы [ 3 ]

5 голосов
/ 16 сентября 2010

Вы можете расширить json.JSONEncoder, чтобы создать свой собственный кодировщик, который сможет работать с объектами datetime.datetime (или объектами любого типа по вашему желанию) таким образом, что создается строка, которая может быть воспроизведена как новая экземпляр datetime.datetime. Я считаю, что это должно быть так просто, как если бы json.JSONEncoder вызывал repr () для ваших экземпляров datetime.datetime.

Процедура того, как это сделать, описана в документах json module .

Модуль json проверяет тип каждого значения, которое необходимо кодировать, и по умолчанию он знает только, как обрабатывать объекты dicts, списки, кортежи, strs, Unicode, int, long, float, boolean и none: -)

Для вас также может быть важен аргумент skipkeys для JSONEncoder.


После прочтения ваших комментариев я пришел к выводу, что не существует простого решения, позволяющего JSONEncoder кодировать ключи словарей с помощью специальной функции. Если вам интересно, вы можете посмотреть на источник и методы iterencode (), которые вызывают _iterencode (), который вызывает _iterencode_dict (), где и возникает ошибка типа.

Проще всего было бы создать новый 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"}'. Для тонкости, оберните его в функцию: -)

2 голосов
/ 10 октября 2014

http://jsonpickle.github.io/ может быть тем, что вы хотите.Столкнувшись с подобной проблемой, я закончил:

to_save = jsonpickle.encode(THE_THING, unpicklable=False, max_depth=4, make_refs=False)
0 голосов
/ 18 апреля 2018

вы можете сделать x = {'alpha': {datetime.date.today().strftime('%d-%m-%Y'): 'abcde'}}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...