2012-05-23 13 views
50

Neden json serileştirmesi, datetime nesneleri için çalışmaz? Json serileştirmesini anladığım kadarıyla, herhangi bir nesne için temel fikir, __str__ yerleşik işlevini çağırıp yanıt olarak aldığınız nesneyi klonlayabilir. Ama zaten mevcut nesneyi stringifying bir __str__ yani bir yolu varken datetime durumunda i aşağıdaki hatayıPython'da datetime nesnelerinin json serileştirmesi, datetime nesneleri için kutunun dışında çalışmaz

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

olsun, Ama bu durumda olacağını neden bunu bilinçli bir kararın gibi görünüyor ?

+8

Json'un nasıl çalıştığını yanlış anlıyorsunuz. __str__ yöntemi ile ilgisi yoktur. JSON bir tarih-zaman türüne sahip değildir, bu nedenle JSON'ta bir tarih-zamanını, alıcı uçta bir çeşit özel mantık olmadan, kayıpsız bir şekilde kodlamak imkansızdır. Böylece kütüphane (mantıksal olarak), bir Unix zaman damgasına veya ISO tarih dizgisine veya bir şeye dönüştürerek bunu yapmanızı sağlar ve bu dönüşümün gerekli olduğunu açıkça belirtir. –

+3

@TylerEaves Bu bir şey ama mantıklı. Bir dize veya int için bir datetime kodlamak ve birçok kez, dict'ten json'a, dedikten sonra python ekosisteminden asla vazgeçmeye gerek olmayan durumları kullanmak mümkündür, ancak json modülü, bu durumu bir özel olmadan ele alamaz datetime işleyici? Gerçekten mi?! Konuyla ilgili çok sayıda stackoverflow sorusuna bakarsak, şüphemde yalnız olmadığımı söyleyebilirim. –

cevap

88

Hayır, json modülünde bu şekilde çalışmıyor. Modül size bir varsayılan kodlayıcı sağlar: json.JSONEncoder. Nesneleri serileştirmek için default yönteminin uygulanmasını sağlamak için bunu genişletmeniz gerekir. Böyle bir şey: diğerleri doğru belirttiği gibi

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) 

, nedeni standard for json tarih saat temsil edilebilir nasıl belirtmez olmasıdır.

+3

Mükemmel cevap. Teşekkürler –

+4

Bu datetime'nin ön uçta nasıl çözüleceği? Bu ondalık kod çözme hakkında soruyorum. – Clayton

+1

@Clayton, JSON yanıtında alacağınız şey unix zaman damgası. [Bu soru] (http://stackoverflow.com/questions/847185/convert-a-unix-timestamp-to-time-in-javascript), bugüne kadar unix zaman damgasının nasıl dönüştürüleceğini anlatıyor. – Vikas

10

Bunların nasıl serileştirilmesini istersiniz?

JSON, tarihlerin nasıl ele alınacağını belirtmez, bu nedenle python json kitaplığı bunları sizin için nasıl temsil edeceğine karar veremez. Bu tamamen diğer tarafın (tarayıcı, betik, her neyse) JSON'da nasıl işlediğine bağlıdır.

+2

Varsayılan bir serileştirme ile mutlaka ilgilenmez. Sadece json formatına girebilmeli ve fazla sorun yaşamadan geri çekilmelisiniz. Kesinlikle datetime üzerinde tamamen başarısız yanlış cevap olarak garanti edilir. –

+0

@JoshuaKolden: ama * değişim biçiminde * dikkatli olmanız gerekir. Java'da veya bir JavaScript uygulamasında JSON kütüphanesi nasıl bir tarih ister? –

+1

Ardından, kişiselleştirilmesi gereken zaman. Python'dan json'a python'a gidersem kutunun dışında, varsayılan olarak ortak veri türleri üzerinde çalışmamak, gereksiz ek yükü ekler. Ayrıca bu diğer diller json'a da standart dönüşümlere sahiptir, bu yüzden bununla iyi bir varsayılan olarak başlayabiliriz. –

8

Seri hale getirme, datetime destekleyecek şekilde json modülünü yamanın basit bir yoludur. Her zaman yaptığın gibi kullanım json serileştirme Daha

import json 
import datetime 

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

- datetime bu kez isoformat olarak tefrika edildikten. Sonuçlanan

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

: '{ "oluşturulmuş": "2015-08-26T14: 21: 31,853855"}': StackOverflow: JSON datetime between Python and JavaScript

+0

En iyi çözüm gördüm. Bir satır yama. –

2

Eğer

fazla ayrıntı ve en dikkatli bazı kelimeler gör Bunu uygulamak zorunda kalmadan datetimes kodlama ve kod çözme almak istiyorsanız, çeşitli popüler türler için kodlama ve kod çözme ekleyen bir sarıcı olan json_tricks'u kullanabilirsiniz.

pip install json_tricks 

ardından .:, json_tricks yerine json den

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

Yasal örneğin içe: Sadece yükleyin benim tarafımdan yapılmış. Çünkü aynı problemi yaşadım. Ama

dumps(obj, default=str) 

bu dezavantajları, örneğin sahip olduğuna dikkat: otomatik dizgelenmiş edilebilir bir şey seri hale getirmek istiyorsanız


, çok kolay, sadece standart bir uygulamayla bunu yapabilir Bunların hiçbiri ekstra çaba gerektirmeden serileştirilmeyecek ve belki de sadece bir şeyi serileştirmek istemiyorsunuz (büyük bir numpy dizisinin bir fonksiyonu gibi) ama bunun yerine bir uyarı olsun, bu yöntem sessiz olacak.

+0

Varsayılan = str. En yaygın durumlar için en kolay düzeltme. – JJC