Tengo un dict básico de la siguiente manera:
sample = {}
sample['title'] = "String"
sample['somedate'] = somedatetimehere
Cuando trato de hacer jsonify(sample)
me sale:
TypeError: datetime.datetime(2012, 8, 8, 21, 46, 24, 862000) is not JSON serializable
¿Qué puedo hacer para que mi muestra de diccionario pueda superar el error anterior?
Nota: Aunque puede no ser relevante, los diccionarios se generan a partir de la recuperación de registros de mongodb
donde imprimo str(sample['somedate'])
, el resultado es 2012-08-08 21:46:24.862000
.
Respuestas:
Actualizado para 2018
La respuesta original acomodaba la forma en que los campos de "fecha" de MongoDB se representaban como:
{"$date": 1506816000000}
Si desea una solución genérica de Python para serializar
datetime
a json, consulte la respuesta de @jjmontes para obtener una solución rápida que no requiera dependencias.Como está usando mongoengine (por comentarios) y pymongo es una dependencia, pymongo tiene utilidades integradas para ayudar con la serialización json:
http://api.mongodb.org/python/1.10.1/api/bson/json_util.html
Ejemplo de uso (serialización):
Ejemplo de uso (deserialización):
Django
Django proporciona un
DjangoJSONEncoder
serializador nativo que se ocupa de este tipo de manera adecuada.Ver https://docs.djangoproject.com/en/dev/topics/serialization/#djangojsonencoder
Una diferencia que noté entre
DjangoJSONEncoder
usar una costumbredefault
como esta:Es que Django despoja un poco de los datos:
Por lo tanto, es posible que tenga que tener cuidado con eso en algunos casos.
fuente
Django MongoDB
. Con la versión posterior, intentaría permanecer dentro del ORM de django para mantener el estado agnóstico del backend. Pero a veces no puede hacer lo que necesita en la abstracción, por lo que despliega una capa. En este caso, no tiene ninguna relación con su problema, ya que solo está utilizando métodos de utilidad para acompañar el formato JSON.Mi rápido y sucio volcado JSON que come fechas y todo:
fuente
default
es una función aplicada a objetos que no son serializables. En este caso lo esstr
, por lo que solo convierte todo lo que no sabe en cadenas. Lo cual es excelente para la serialización, pero no tan bueno cuando se deserializa (de ahí el "rápido y sucio"), ya que cualquier cosa podría haber sido encadenada sin previo aviso, por ejemplo, una función o matriz numpy.json.dumps({():1,type(None):2},default=str)
aumentosTypeError
, no puede tener tipografía o tupla.Sobre la base de otras respuestas, una solución simple basada en un serializador específico que simplemente convierte
datetime.datetime
ydatetime.date
objetos en cadenas.Como se ve, el código solo comprueba si el objeto es de clase
datetime.datetime
odatetime.date
, y luego lo utiliza.isoformat()
para producir una versión serializada del mismo, de acuerdo con el formato ISO 8601, AAAA-MM-DDTHH: MM: SS (que se decodifica fácilmente por JavaScript ) Si se buscan representaciones serializadas más complejas, se podría usar otro código en lugar de str () (vea otras respuestas a esta pregunta para ver ejemplos). El código termina con una excepción, para tratar el caso en que se llama con un tipo no serializable.Esta función json_serial se puede usar de la siguiente manera:
Los detalles sobre cómo funciona el parámetro predeterminado para json.dumps se pueden encontrar en la Sección Uso básico de la documentación del módulo json .
fuente
01:00:00+01:00
y02:00:00+00:00
no se supone que sean iguales, según el contexto. Se refieren al mismo punto en el tiempo, por supuesto, pero la compensación podría ser un aspecto relevante del valor.Acabo de encontrar este problema y mi solución es subclasificar
json.JSONEncoder
:En su llamada, haga algo como:
json.dumps(yourobj, cls=DateTimeEncoder)
Lo.isoformat()
que obtuve de una de las respuestas anteriores.fuente
DjangoJSONEncoder
. docs.djangoproject.com/en/dev/topics/serialization/…return super(DateTimeEncoder, self).default(o)
return super().default(o)
Convierte la fecha en una cadena
fuente
oDate = datetime.datetime.strptime(sDate, '%Y-%m-%d %H:%M:%S.%f')
. Formatos obtenidos de: docs.python.org/2/library/datetime.html.now()
utiliza la hora local, sin indicar esto. Al menos se.utcnow()
debe usar (y luego se agrega un +0000 o Z)At least .utcnow() should be used
No exactamente,datetime.now(timezone.utc)
se recomienda, vea la advertencia en: docs.python.org/3.8/library/… .Para otros que no necesitan o quieren usar la biblioteca pymongo para esto ... puede lograr la conversión JSON de fecha y hora fácilmente con este pequeño fragmento:
Luego úsalo así:
salida:
fuente
millis=
debe sangrar dentro de la declaración if? También es probablemente mejor usar str (obj) para obtener el formato ISO, que creo que es más común.datetime.now()
devuelve la hora local (como un objeto de fecha y hora ingenuo) pero su código supone queobj
está en UTC si no reconoce la zona horaria. Usar en sudatetime.utcnow()
lugar.Aquí está mi solución:
Entonces puedes usarlo así:
fuente
isinstance(obj, datetime.datetime)
dentro de TypeError, agregar más tipos para manejar y terminar constr(obj)
orepr(obj)
. Y todos sus volcados solo pueden apuntar a esta clase especializada.Tengo una aplicación con un problema similar; mi enfoque era JSONize el valor de fecha y hora como una lista de 6 elementos (año, mes, día, hora, minutos, segundos); podría ir a microsegundos como una lista de 7 elementos, pero no tuve necesidad de:
produce:
fuente
Mi solución (con menos verbosidad, creo):
Luego use en
jsondumps
lugar dejson.dumps
. Imprimirá:Si quiere, más adelante puede agregar otros casos especiales a esto con un simple giro del
default
método. Ejemplo:fuente
Este Q se repite una y otra vez, una forma simple de parchear el módulo json de modo que la serialización admita fecha y hora.
Luego use la serialización json como siempre lo hace, esta vez con la fecha y hora siendo serializada como isoformat.
Resultando en: '{"creado": "2015-08-26T14: 21: 31.853855"}'
Vea más detalles y algunas palabras de precaución en: StackOverflow: fecha y hora JSON entre Python y JavaScript
fuente
El método json.dumps puede aceptar un parámetro opcional llamado predeterminado que se espera que sea una función. Cada vez que JSON intenta convertir un valor, no sabe cómo convertirlo, llamará a la función que le pasamos. La función recibirá el objeto en cuestión y se espera que devuelva la representación JSON del objeto.
fuente
si está usando python3.7, entonces la mejor solución es usar
datetime.isoformat()
ydatetime.fromisoformat()
; trabajan condatetime
objetos ingenuos y conscientes :salida:
si está utilizando python3.6 o inferior, y solo le importa el valor del tiempo (no la zona horaria), puede usar
datetime.timestamp()
y en sudatetime.fromtimestamp()
lugar;si está utilizando python3.6 o inferior, y le importa la zona horaria, puede obtenerla
datetime.tzinfo
, pero debe serializar este campo usted mismo; la forma más fácil de hacer esto es agregar otro campo_tzinfo
en el objeto serializado;finalmente, tenga cuidado con las precisiones en todos estos ejemplos;
fuente
Debe usar
.strftime()
método en.datetime.now()
método para hacerlo como un método serializable .Aquí hay un ejemplo:
Salida:
fuente
Aquí hay una solución simple para superar el problema "datetime no JSON serializable"
Salida: -> {"fecha": "2015-12-16T04: 48: 20.024609"}
fuente
Debe proporcionar una clase de codificador personalizado con el
cls
parámetro dejson.dumps
. Para citar de los documentos :Esto utiliza números complejos como ejemplo, pero puede crear fácilmente una clase para codificar fechas (excepto que creo que JSON es un poco confuso sobre las fechas)
fuente
La forma más sencilla de hacer esto es cambiar la parte del dict que está en formato de fecha y hora a isoformat. Ese valor será efectivamente una cadena en isoformat con la que json está bien.
fuente
En realidad es bastante simple. Si necesita serializar fechas con frecuencia, trabaje con ellas como cadenas. Puede convertirlos fácilmente de nuevo como objetos de fecha y hora si es necesario.
Si necesita trabajar principalmente como objetos de fecha y hora, conviértalos como cadenas antes de serializar.
Como puede ver, la salida es la misma en ambos casos. Solo el tipo es diferente.
fuente
Si está utilizando el resultado en una vista, asegúrese de devolver una respuesta adecuada. Según la API, jsonify hace lo siguiente:
Para imitar este comportamiento con json.dumps, debe agregar algunas líneas de código adicionales.
También debe devolver un dict para replicar completamente la respuesta de jsonify. Entonces, el archivo completo se verá así
fuente
pymongo
.Pruebe este con un ejemplo para analizarlo:
fuente
Mi solución ...
Ok, ahora algunas pruebas.
fuente
Aquí está mi solución completa para convertir datetime a JSON y viceversa.
Salida
Archivo JSON
Esto me ha permitido importar y exportar cadenas, ints, flotantes y objetos de fecha y hora. No debería ser demasiado difícil de extender para otros tipos.
fuente
TypeError: 'str' does not support the buffer interface
. Es por'wb'
el modo abierto, debería ser'w'
. También sopla en la deserialización cuando tenemos datos similares a la fecha,'0000891618-05-000338'
pero no coinciden con el patrón.Convierte el
date
astring
fuente
En general, hay varias formas de serializar fechas y horas, como:
Si está de acuerdo con la última forma, el paquete json_tricks maneja fechas, horas y horas, incluidas las zonas horarias.
lo que da:
Entonces todo lo que necesitas hacer es
y luego importar desde en
json_tricks
lugar dejson
.La ventaja de no almacenarlo como una sola cadena, int o flotante viene cuando se decodifica: si encuentra solo una cadena o especialmente int o flotante, necesita saber algo sobre los datos para saber si es una fecha y hora. Como dict, puede almacenar metadatos para que puedan decodificarse automáticamente, que es lo que
json_tricks
hace por usted. También es fácilmente editable para humanos.Descargo de responsabilidad: está hecho por mí. Porque tuve el mismo problema.
fuente
Recibí el mismo mensaje de error al escribir el decorador de serialización dentro de una Clase con sqlalchemy. Entonces en lugar de:
Simplemente tomé prestada la idea de jgbarah de usar isoformat () y agregué el valor original con isoformat (), para que ahora se vea así:
fuente
Una solución rápida si quieres tu propio formato
fuente
Si está en ambos lados de la comunicación, puede usar las funciones repr () y eval () junto con json.
No debe importar datetime como
ya que eval se quejará. O puede pasar datetime como parámetro para evaluar. En cualquier caso, esto debería funcionar.
fuente
Encontré el mismo problema al externalizar el objeto del modelo django para volcarlo como JSON. Así es como puedes resolverlo.
fuente
Uso de la utilidad anterior:
fuente
Esta biblioteca superjson puede hacerlo. Y puede personalizar fácilmente el serializador json para su propio objeto Python siguiendo estas instrucciones https://superjson.readthedocs.io/index.html#extend .
El concepto general es:
su código necesita ubicar el método correcto de serialización / deserialización basado en el objeto python. Por lo general, el nombre de clase completo es un buen identificador.
Y luego, su método ser / deser debería poder transformar su objeto en un objeto serializable Json normal, una combinación de tipo genérico de python, dict, list, string, int, float. E implemente su método de diseño inversamente.
fuente
Puede que no sea 100% correcto, pero esta es la forma simple de serializar
fuente