Почему json-сериализация объектов datetime в python не работает "из коробки" для объектов datetime

Почему сериализация json не работает для объектов datetime. Как я понимаю сериализацию JSON, основной идеей для любого объекта можно назвать__str__ встроенная функция, а затем urlencode объекта, который вы получите в ответ. Но в случае datetime я получаю следующую ошибку

TypeError: datetime.datetime(2012, 5, 23, 18, 38, 23, 37566) is not JSON serializable

пока есть__str__ то есть способ упорядочения уже доступного объекта, но кажется сознательным решением не делать этого, почему это так?

 Joshua Kolden26 апр. 2015 г., 23:37
@TylerEaves Это совсем не логично. Можно без потерь кодировать дату и время в строку или int, и во многих случаях используется преобразование из dict в json, чтобы снова диктовать никогда не покидать экосистему python, однако модуль json не может обработать этот случай без пользовательского обработчик даты и времени? В самом деле?! Глядя на большое количество вопросов о переполнении стека по этой теме, я бы сказал, что я не одинок в своей недоверчивости.
 Tyler Eaves23 мая 2012 г., 15:56
Вы неправильно понимаете, как работает JSON. Это не имеет ничего общего сstr метод. JSON не имеет типа даты-времени, периода, поэтому невозможно кодировать дату-время без потерь в JSON без какой-либо специальной логики на принимающей стороне. Таким образом, библиотека (по логике) заставляет вас делать это самостоятельно, конвертируя в метку времени Unix или строку даты ISO или что-то в этом роде и делая явным, что преобразование необходимо.

Ответы на вопрос(4)

JSON не указывает, как обрабатывать даты, поэтому Pythonjson библиотека не может принять решение о том, как затем представлять их для вас. Это полностью зависит от того, как другая сторона (браузер, скрипт, что угодно) также обрабатывает даты в JSON.

 27 апр. 2015 г., 00:17
Нет, такого дефолта нет. Стандарт не определяет какой-либо.
 26 апр. 2015 г., 23:47
Тогда это то, когда нужно будет настроить. Из коробки, если я просто перехожу с python на json на python, по умолчанию не работает с общими типами данных, просто добавляет ненужные накладные расходы. Кроме того, эти другие языки также имеют стандартные преобразования в json, так что можно просто начать с этого как хорошего значения по умолчанию.
 27 апр. 2015 г., 00:41
И это мешает Python кодировать datetime, почему? Другие языки не имеют такой проблемы. Абстракция данных Json делает егоmore Тип гибкий, не менее. Большинство языков выбирают (для себя) кодировку строки даты и времени по умолчанию, а затем, по крайней мере, имеют возможность последовательно считывать и записывать значения даты и времени в json на одном языке. Python вызывает несовместимость не только с внешними системами, но даже с двумя различными приложениями Python могут по-разному обрабатывать datetime / json.
 26 апр. 2015 г., 23:43
С сериализацией по умолчанию не обязательно заботиться. Вам просто нужно иметь возможность войти в формат JSON и вернуться без особых проблем. Несомненно, что неудача в datetime полностью будет неправильным ответом.
 27 апр. 2015 г., 01:09
Нетрудно выбрать формат, но это еще не все, что нужно делать. В качестве примера, нетривиально заставить sqlalchemy работать со словарями (содержащими datetime на разных уровнях вложенности), вставленными в столбцы JSON postgresql. Тривиальная задача в go, ruby и javascript. В конце концов, это всего лишь сериализация словаря / хэша, но Python не может этого сделать. питонdoes сделайте выбор с точки зрения того, какой формат является приемлемым для создания даты и времени из строк, и существуют также общие стандарты, поэтому «философия python» кажется в лучшем случае круговая логика в этом случае.

одимости его реализации, вы можете использоватьjson_tricks, который является оберткой, которая добавляет кодирование и декодирование для различных популярных типов. Просто установите:

pip install json_tricks

а затем импортировать изjson_tricks вместоjsonНапример:

from json_tricks import dumps, loads
json = dumps({'name': 'MyName', 'birthday': datetime.datetime(1992, 5, 23, 18, 38, 23, 37566)})
me = loads(json)

Отказ от ответственности: это сделано мной. Потому что у меня была такая же проблема.

Если вы хотите автоматически сериализовать все, что может быть преобразовано в строку, вы можете сделать это просто с помощью стандартной реализации:

dumps(obj, default=str)

Но обратите внимание, что это имеет недостатки, например, ни одна из них не будет десериализована без дополнительных усилий, и, возможно, иногда вы просто не хотите сериализовать что-либо (например, функцию большого массива с пустым массивом), но вместо этого получите предупреждение, которое этот метод будет отключать.

 27 сент. 2017 г., 21:00
Приятно упомянуть default = str. Самое простое решение для наиболее распространенных ситуаций.

чтобы сериализация поддерживала дату и время.

import json
import datetime

json.JSONEncoder.default = lambda self,obj: (obj.isoformat() if isinstance(obj, datetime.datetime) else None)

Чем использовать сериализацию JSON, как вы всегда делаете - на этот раз с датой и временем сериализуется как изоформат.

json.dumps({'created':datetime.datetime.now()})

В результате: "{" создан ":" 2015-08-26T14: 21: 31.853855 "}"

Смотрите более подробную информацию и некоторые слова предостережения на: StackOverflow: JSON datetime между Python и JavaScript

 15 мар. 2016 г., 00:45
Решение Вопроса

json модуль. Модуль предоставляет вам кодировщик по умолчанию:json.JSONEncoder, Вы должны расширить это, чтобы обеспечить реализациюdefault метод для сериализации объектов. Что-то вроде этого:

import json
import datetime
from time import mktime

class MyEncoder(json.JSONEncoder):

    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return int(mktime(obj.timetuple()))

        return json.JSONEncoder.default(self, obj)

print json.dumps(obj, cls=MyEncoder)

Как правильно отметили другие, причина в том, чтостандарт для JSON не указывает, как можно представить дату и время.

 20 февр. 2014 г., 07:57
как декодировать эту дату и время в интерфейсе? я спрашиваю о расшифровке этого десятичного числа.
 22 февр. 2015 г., 16:29
@Vikas Спасибо. Я следовал вашему коду, но немного изменилisinstance проверить часть кif isinstance (obj, datetime.datetime): return obj.strftime ('%Y/%m/%d/%H/%M/%S') elif isinstance (obj, datetime.date): return obj.strftime ('%Y/%m/%d').
 12 мая 2013 г., 19:16
Отличный ответ. Спасибо
 24 июн. 2016 г., 21:04
Что ж, использование mktime работает, я нашел то, что считаю лучшим способом. JSON использует форматирование ISO 8601 для своих отметок времени. Чтобы получить тот же вид форматирования времени из Python, все, что вам нужно сделать, это взять ваш объект datetime и добавить.isoformat() к концу.
 23 окт. 2014 г., 21:13
@Clayton, в ответе JSON вы получите метку времени Unix.This question ответы, как конвертировать метку времени Unix в дату.

Ваш ответ на вопрос