[python] “JSON serializable이 아닌 datetime.datetime”을 극복하는 방법은 무엇입니까?

다음과 같은 기본 dict이 있습니다.

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

내가하려고 jsonify(sample)하면 :

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

사전 샘플이 위의 오류를 극복 할 수 있도록 어떻게해야합니까?

참고 : 관련성이 없지만 사전을 mongodb인쇄 할 때 레코드를 검색하면 사전이 str(sample['somedate'])출력됩니다 2012-08-08 21:46:24.862000.



답변

2018 년 업데이트

원래 답변은 MongoDB “날짜”필드가 다음과 같이 표시되는 방식을 수용했습니다.

{"$date": 1506816000000}

datetimejson 으로 직렬화 하기 위한 일반적인 Python 솔루션을 원한다면 종속성이 필요없는 빠른 솔루션에 대한 @jjmontes의 답변 을 확인하십시오 .


mongoengine을 사용하고 (댓글 당) pymongo는 종속이므로 pymongo에는 json 직렬화를 돕는 내장 유틸리티가 있습니다.
http://api.mongodb.org/python/1.10.1/api/bson/json_util.html

사용 예 (직렬화) :

from bson import json_util
import json

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

사용 예 (직렬화 해제) :

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

장고

Django는 DjangoJSONEncoder이러한 종류의 올바르게 처리 하는 기본 직렬 변환기를 제공합니다 .

https://docs.djangoproject.com/en/dev/topics/serialization/#djangojsonencoder를 참조 하십시오.

from django.core.serializers.json import DjangoJSONEncoder

return json.dumps(
  item,
  sort_keys=True,
  indent=1,
  cls=DjangoJSONEncoder
)

다음 과 같이 DjangoJSONEncoder커스텀을 사용하고 사용하는 것의 차이점은 default다음과 같습니다.

import datetime
import json

def default(o):
    if isinstance(o, (datetime.date, datetime.datetime)):
        return o.isoformat()

return json.dumps(
  item,
  sort_keys=True,
  indent=1,
  default=default
)

장고가 약간의 데이터를 제거한다는 것입니까?

 "last_login": "2018-08-03T10:51:42.990", # DjangoJSONEncoder 
 "last_login": "2018-08-03T10:51:42.990239", # default

따라서 경우에 따라주의해야 할 수도 있습니다.


답변

날짜와 모든 것을 먹는 내 빠르고 더러운 JSON 덤프 :

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


답변

특정 시리얼에 따라 다른 답변에 구축, 간단한 해결책이 바로 변환 datetime.datetimedatetime.date문자열을 객체.

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))

보시다시피 코드는 객체가 클래스 datetime.datetime인지 또는인지 확인한 다음 ISO 8601 형식 YYYY-MM-DDTHH : MM : SS (JavaScript로 쉽게 디코딩 됨)에 따라 직렬화 된 버전을 생성하는 datetime.date데 사용 .isoformat()합니다. ). 보다 복잡한 직렬화 표현을 원한다면 str () 대신 다른 코드를 사용할 수 있습니다 (예제에 대해서는이 질문에 대한 다른 답변 참조). 코드는 직렬화 불가능 유형으로 호출되는 경우를 처리하기 위해 예외를 발생시켜 종료됩니다.

이 json_serial 함수는 다음과 같이 사용할 수 있습니다.

from datetime import datetime
from json import dumps

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

json.dumps에 대한 기본 매개 변수 작동 방식에 대한 자세한 내용은 json 모듈 설명서의 기본 사용법 섹션을 참조하십시오 .


답변

방금이 문제가 발생했으며 솔루션은 서브 클래스입니다 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)

: 통화에서 같은 것을 할 나는 위의 답변 중 하나를 얻었다.json.dumps(yourobj, cls=DateTimeEncoder).isoformat()


답변

날짜를 문자열로 변환

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


답변

이것을 위해 pymongo 라이브러리를 필요로하지 않거나 사용하지 않으려는 다른 사람들을 위해이 작은 스 니펫으로 날짜 시간 JSON 변환을 쉽게 달성 할 수 있습니다.

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,))

그런 다음 다음과 같이 사용하십시오.

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

산출: 

'1365091796124'


답변

내 해결책은 다음과 같습니다.

# -*- 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)

그런 다음 다음과 같이 사용할 수 있습니다.

json.dumps(dictionnary, cls=DatetimeEncoder)