Quiero enviar un objeto datetime.datetime en forma serializada desde Python usando JSON y deserializar en JavaScript usando JSON. ¿Cuál es la mejor manera de hacer esto?
javascript
python
json
Peter Mortensen
fuente
fuente
Respuestas:
Puede agregar el parámetro 'predeterminado' a json.dumps para manejar esto:
Cuál es el formato ISO 8601 .
Una función de controlador predeterminada más completa:
Actualización: salida agregada de tipo y valor.
Actualización: también maneja la fecha
fuente
dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime) else json.JSONEncoder().default(obj)
Para proyectos en varios idiomas, descubrí que las cadenas que contienen fechas RfC 3339 son la mejor opción . Una fecha RfC 3339 se ve así:
Creo que la mayoría del formato es obvio. La única cosa algo inusual puede ser la "Z" al final. Es sinónimo de GMT / UTC. También puede agregar un desplazamiento de zona horaria como +02: 00 para CEST (Alemania en verano). Personalmente prefiero mantener todo en UTC hasta que se muestre.
Para la visualización, las comparaciones y el almacenamiento, puede dejarlo en formato de cadena en todos los idiomas. Si necesita la fecha para realizar los cálculos, vuelva a convertirla en un objeto de fecha nativo en la mayoría de los idiomas.
Así que genera el JSON así:
Desafortunadamente, el constructor Fecha de Javascript no acepta cadenas RfC 3339 pero hay muchos analizadores disponibles en Internet.
huTools.hujson intenta manejar los problemas de codificación más comunes que puede encontrar en el código de Python, incluidos los objetos de fecha / fecha y hora, mientras maneja las zonas horarias correctamente.
fuente
datetime
: datetime.isoformat () como porsimplejson
, que volcará losdatetime
objetos comoisoformat
cadenas de forma predeterminada. No hay necesidad destrftime
piratería manual .datetime
objetos a laisoformat
cadena. Para mí, lossimplejson.dumps(datetime.now())
rendimientosTypeError: datetime.datetime(...) is not JSON serializable
json.dumps(datetime.datetime.now().isoformat())
Es donde sucede la magia.Lo he resuelto.
Digamos que tiene un objeto de fecha y hora de Python, d , creado con datetime.now (). Su valor es:
Puede serializarlo a JSON como una cadena de fecha y hora ISO 8601:
El objeto de fecha y hora de ejemplo se serializaría como:
Este valor, una vez recibido en la capa Javascript, puede construir un objeto Date:
A partir de Javascript 1.8.5, los objetos Date tienen un método toJSON, que devuelve una cadena en un formato estándar. Para serializar el objeto Javascript anterior de nuevo a JSON, por lo tanto, el comando sería:
Lo que te daría:
Esta cadena, una vez recibida en Python, podría deserializarse de nuevo a un objeto de fecha y hora:
Esto da como resultado el siguiente objeto de fecha y hora, que es el mismo con el que comenzó y, por lo tanto, correcto:
fuente
Utilizando
json
, puede subclasificar JSONEncoder y anular el método predeterminado () para proporcionar sus propios serializadores personalizados:Entonces, puedes llamarlo así:
fuente
obj.isoformat()
. También puede usar ladumps()
llamada más común , que toma otrosindent
argumentos útiles (como ): simplejson.dumps (myobj, cls = JSONEncoder, ...)Aquí hay una solución bastante completa para codificar y decodificar recursivamente los objetos datetime.datetime y datetime.date utilizando el
json
módulo de biblioteca estándar . Esto necesita Python> = 2.6 ya que el%f
código de formato en la cadena de formato datetime.datetime.strptime () solo es compatible desde entonces. Para el soporte de Python 2.5, suelte%f
y quite los microsegundos de la cadena de fecha ISO antes de intentar convertirlo, pero perderá precisión de microsegundos, por supuesto. Para la interoperabilidad con las cadenas de fecha ISO de otras fuentes, que pueden incluir un nombre de zona horaria o desplazamiento UTC, es posible que también necesite quitar algunas partes de la cadena de fecha antes de la conversión. Para obtener un analizador completo de cadenas de fecha ISO (y muchos otros formatos de fecha), consulte el dateutil de terceros módulo .La decodificación solo funciona cuando las cadenas de fecha ISO son valores en una notación de objeto literal de JavaScript o en estructuras anidadas dentro de un objeto. Las cadenas de fecha ISO, que son elementos de una matriz de nivel superior, no se decodificarán.
Es decir, esto funciona:
Y esto también:
Pero esto no funciona como se esperaba:
Aquí está el código:
fuente
datetime.datetime.utcnow().isoformat()[:-3]+"Z"
si fuera exactamente como lo que JSON.stringify () produce en javascriptSi está seguro de que solo Javascript consumirá el JSON, prefiero pasar Javascript
Date
objetos directamente.El
ctime()
método en losdatetime
objetos devolverá una cadena que el objeto Fecha de Javascript puede entender.Javascript lo usará felizmente como un objeto literal, y tienes tu objeto Date integrado.
fuente
.ctime()
es una manera MUY mala de pasar información de tiempo,.isoformat()
es mucho mejor. Lo que.ctime()
hace es tirar la zona horaria y el horario de verano como si no existieran. Esa función debería ser eliminada.Tarde en el juego ... :)
Una solución muy simple es parchear el módulo json predeterminado. Por ejemplo:
Ahora, puede usar json.dumps () como si siempre hubiera admitido datetime ...
Esto tiene sentido si necesita que esta extensión del módulo json se active siempre y no desee cambiar la forma en que usted u otros usan la serialización json (ya sea en el código existente o no).
Tenga en cuenta que algunos pueden considerar parchear bibliotecas de esa manera como una mala práctica. Se debe tener especial cuidado en caso de que desee extender su aplicación de más de una manera; en tal caso, sugiero usar la solución por ramen o JT y elegir la extensión json adecuada en cada caso.
fuente
None
. Es posible que desee lanzar una excepción en su lugar.¡No hay mucho que agregar a la respuesta wiki de la comunidad, a excepción de la marca de tiempo !
Javascript usa el siguiente formato:
Lado de Python (para el
json.dumps
controlador, vea las otras respuestas):Si deja esa Z fuera, los marcos frontend como angular no pueden mostrar la fecha en la zona horaria local del navegador:
fuente
En el lado de Python:
En el lado de javascript:
donde los datos son resultado de python
fuente
Mi consejo es usar una biblioteca. Hay varios disponibles en pypi.org.
Yo uso este, funciona bien: https://pypi.python.org/pypi/asjson
fuente
Aparentemente, el formato de fecha JSON "correcto" (bien JavaScript) es 2012-04-23T18: 25: 43.511Z - UTC y "Z". Sin esto, JavaScript utilizará la zona horaria local del navegador web al crear un objeto Date () a partir de la cadena.
Por un tiempo "ingenuo" (lo que Python llama un tiempo sin zona horaria y esto supone que es local) lo siguiente forzará la zona horaria local para que luego se pueda convertir correctamente a UTC:
Por qué es tan difícil.
fuente
Para la conversión de fecha de Python a JavaScript, el objeto de fecha debe estar en formato ISO específico, es decir, formato ISO o número UNIX. Si el formato ISO carece de información, puede convertirlo al número de Unix con Date.parse primero. Además, Date.parse también funciona con React, mientras que la nueva Fecha podría desencadenar una excepción.
En caso de que tenga un objeto DateTime sin milisegundos, debe considerarse lo siguiente. :
La fecha de ejemplo también podría ser una variable en el objeto result.data después de una llamada a la API.
Para ver las opciones para mostrar la fecha en el formato deseado (por ejemplo, para mostrar los días de semana largos), consulte el documento MDN .
fuente