Hier ist eine ziemlich vollständige Lösung für die rekursive Codierung und Decodierung von datetime.datetime- und datetime.date-Objekten unter Verwendung des Standardbibliotheksmoduls json
. Dies erfordert Python >= 2.6, da der Formatcode %f
im datetime.datetime.strptime() Formatstring erst seitdem unterstützt wird. Für Python 2.5-Unterstützung entfernen Sie %f
und Strippen der Mikrosekunden aus der ISO 8601 Datumsschnur, bevor Sie versuchen, sie umzuwandeln, aber Sie verlieren natürlich die Mikrosekundenpräzision. Für die Interoperabilität mit ISO 8601-Datumsschnüren aus anderen Quellen, die einen Zeitzonennamen oder UTC-Versatz enthalten können, müssen Sie möglicherweise auch einige Teile der Datumsschnur vor der Konvertierung entfernen. Für einen vollständigen Parser für ISO 8601-Datumsschnüre (und viele andere Datumsformate) sehen Sie das externe Modul dateutil.
Die Dekodierung funktioniert nur, wenn die ISO 8601-Datumsschnüre Werte in einer JavaScript Literalobjektdarstellung oder in verschachtelten Strukturen innerhalb eines Objekts sind. ISO 8601-Datumsschnüre, die Elemente eines Arrays der obersten Ebene sind, werden nicht dekodiert.
D.h. das funktioniert:
Datum = datetime.datetime.now()
>>> json = dumps(dict(foo='bar', innerdict=dict(date=date)))
>>> json
'{"innerdict": {"date": "2010-07-15T13:16:38.365579"}, "foo": "bar"}'
>>> loads(json)
{u'innerdict': {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)},
u'foo': u'bar'}
Und das auch:
>>> json = dumps(['foo', 'bar', dict(date=date)])
>>> json
'["foo", "bar", {"date": "2010-07-15T13:16:38.365579"}]'
>>> loads(json)
[u'foo', u'bar', {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)}]
Aber das funktioniert nicht wie erwartet:
>>> json = dumps(['foo', 'bar', date])
>>> json
'["foo", "bar", "2010-07-15T13:16:38.365579"]'
>>> loads(json)
[u'foo', u'bar', u'2010-07-15T13:16:38.365579']
Hier ist der Code:
__all__ = ['dumps', 'loads']
import datetime
try:
import json
except ImportError:
import simplejson as json
class JSONDateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (datetime.date, datetime.datetime)):
return obj.isoformat()
else:
return json.JSONEncoder.default(self, obj)
def datetime_decoder(d):
if isinstance(d, list):
pairs = enumerate(d)
elif isinstance(d, dict):
pairs = d.items()
result = []
for k,v in pairs:
if isinstance(v, basestring):
try:
# Der Formatcode %f wird nur in Python >= 2.6 unterstützt.
# Für Python <= 2.5, Mikrosekunden abschneiden
# v = datetime.datetime.strptime(v.rsplit('.', 1)[0],
# '%Y-%m-%dT%H:%M:%S')
v = datetime.datetime.strptime(v, '%Y-%m-%dT%H:%M:%S.%f')
except ValueError:
try:
v = datetime.datetime.strptime(v, '%Y-%m-%d').date()
except ValueError:
pass
elif isinstance(v, (dict, list)):
v = datetime_decoder(v)
result.append((k, v))
if isinstance(d, list):
return [x[1] for x in result]
elif isinstance(d, dict):
return dict(result)
def dumps(obj):
return json.dumps(obj, cls=JSONDateTimeEncoder)
def loads(obj):
return json.loads(obj, object_hook=datetime_decoder)
if __name__ == '__main__':
mytimestamp = datetime.datetime.utcnow()
mydate = datetime.date.today()
data = dict(
foo = 42,
bar = [mytimestamp, mydate],
date = mydate,
timestamp = mytimestamp,
struct = dict(
date2 = mydate,
timestamp2 = mytimestamp
)
)
print repr(data)
jsonstring = dumps(data)
print jsonstring
print repr(loads(jsonstring))
0 Stimmen
Bevorzugen Sie die Verwendung einer Bibliothek oder möchten Sie dies selbst codieren?