Question Comment surmonter "datetime.datetime pas JSON serializable"?


J'ai une dict de base comme suit:

sample = {}
sample['title'] = "String"
sample['somedate'] = somedatetimehere

Quand j'essaie de faire jsonify(sample) Je reçois:

TypeError: datetime.datetime(2012, 8, 8, 21, 46, 24, 862000) is not JSON serializable

Que puis-je faire pour que mon exemple de dictionnaire puisse surmonter l'erreur ci-dessus?

Note: Bien que cela ne soit pas pertinent, les dictionnaires sont générés à partir de la récupération d'enregistrements à partir de mongodb où lorsque j'imprime str(sample['somedate']), la sortie est 2012-08-08 21:46:24.862000.


425
2017-08-09 02:02


origine


Réponses:


Mise à jour pour 2018

La réponse originale correspondait à la manière dont les champs "date" de MongoDB étaient représentés comme suit:

{"$date": 1506816000000}

Si vous voulez une solution Python générique pour la sérialisation datetime à json, vérifier La réponse de @jjmontes pour une solution rapide qui ne nécessite aucune dépendance.


Comme vous utilisez mongoengine (par commentaires) et pymongo est une dépendance, pymongo a des utilitaires intégrés pour aider à la sérialisation json:
http://api.mongodb.org/python/1.10.1/api/bson/json_util.html

Exemple d'utilisation (sérialisation):

from bson import json_util
import json

json.dumps(anObject, default=json_util.default)

Exemple d'utilisation (désérialisation):

json.loads(aJsonString, object_hook=json_util.object_hook)

212
2017-08-09 02:07



S'appuyant sur d'autres réponses, une solution simple basée sur un sérialiseur spécifique qui convertit simplement datetime.datetime et datetime.date objets aux chaînes.

from datetime import date, datetime

def json_serial(obj):
    """JSON serializer for objects not serializable by default json code"""

    if isinstance(obj, (datetime, date)):
        return obj.isoformat()
    raise TypeError ("Type %s not serializable" % type(obj))

Comme vu, le code vérifie juste pour savoir si l'objet est de classe datetime.datetime ou datetime.date, puis utilise .isoformat() pour en produire une version sérialisée, selon le format ISO 8601, AAAA-MM-DDTHH: MM: SS (qui est facilement décodé par JavaScript). Si des représentations sérialisées plus complexes sont recherchées, d'autres codes pourraient être utilisés à la place de str () (voir d'autres exemples de réponses à cette question). Le code se termine par une exception, pour traiter le cas où il est appelé avec un type non sérialisable.

Cette fonction json_serial peut être utilisée comme suit:

from datetime import datetime
from json import dumps

print dumps(datetime.now(), default=json_serial)

Les détails sur le fonctionnement du paramètre par défaut json.dumps se trouvent dans Section Utilisation basique de la documentation du module json.


332
2018-03-06 23:46



Mon vidage JSON rapide et sale qui mange des dates et tout:

json.dumps(my_dictionary, indent=4, sort_keys=True, default=str)

216
2018-03-21 22:29



Je viens de rencontrer ce problème et ma solution est de sous-classer json.JSONEncoder:

from datetime import datetime
import json

class DateTimeEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, datetime):
            return o.isoformat()

        return json.JSONEncoder.default(self, o)

Dans votre appel, faites quelque chose comme: json.dumps(yourobj, cls=DateTimeEncoder) le .isoformat() J'ai obtenu de l'une des réponses ci-dessus.


143
2017-11-21 09:52



Convertir la date en chaîne

sample['somedate'] = str( datetime.utcnow() )

110
2017-08-09 02:10



Pour les autres qui n'ont pas besoin ou ne veulent pas utiliser la bibliothèque pymongo pour cela, vous pouvez facilement réaliser la conversion JSON de datetime avec ce petit extrait:

def default(obj):
    """Default JSON serializer."""
    import calendar, datetime

    if isinstance(obj, datetime.datetime):
        if obj.utcoffset() is not None:
            obj = obj - obj.utcoffset()
        millis = int(
            calendar.timegm(obj.timetuple()) * 1000 +
            obj.microsecond / 1000
        )
        return millis
    raise TypeError('Not sure how to serialize %s' % (obj,))

Alors utilisez-le comme ça:

import datetime, json
print json.dumps(datetime.datetime.now(), default=default)

sortie:

'1365091796124'

75
2018-04-04 23:15



Voici ma solution:

# -*- coding: utf-8 -*-
import json


class DatetimeEncoder(json.JSONEncoder):
    def default(self, obj):
        try:
            return super(DatetimeEncoder, obj).default(obj)
        except TypeError:
            return str(obj)

Alors vous pouvez l'utiliser comme ça:

json.dumps(dictionnary, cls=DatetimeEncoder)

28
2018-05-03 06:38



J'ai une application avec un problème similaire; mon approche consistait à JSONize la valeur datetime comme une liste de six éléments (année, mois, jour, heure, minutes, secondes); vous pourriez aller aux microsecondes comme une liste de 7 éléments, mais je n'avais pas besoin de:

class DateTimeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            encoded_object = list(obj.timetuple())[0:6]
        else:
            encoded_object =json.JSONEncoder.default(self, obj)
        return encoded_object

sample = {}
sample['title'] = "String"
sample['somedate'] = datetime.datetime.now()

print sample
print json.dumps(sample, cls=DateTimeEncoder)

produit:

{'somedate': datetime.datetime(2013, 8, 1, 16, 22, 45, 890000), 'title': 'String'}
{"somedate": [2013, 8, 1, 16, 22, 45], "title": "String"}

20
2017-08-01 23:27