JSON.loads를 사용하여 Python datetime 개체로 변환하려면 어떻게 해야 합니까?
JSON 개체를 문자열로 표현했습니다.
dumped_dict = '{"debug": false, "created_at": "2020-08-09T11:24:20"}'
이 오브젝트를 사용하여 json.loads를 호출하면
json.loads(dumped_dict)
알겠습니다.
{'created_at': '2020-08-09T11:24:20', 'debug': False}
여긴 아무 문제 없어요단, 위의 오브젝트를 json.loads로 다음과 같이 변환할 수 있는 방법이 있는지 알고 싶습니다.
{'created_at': datetime.datetime(2020, 08, 09, 11, 24, 20), 'debug': False}
json.loads를 호출하는 동안 datetime 문자열을 실제 datetime.datetime 개체로 변환할 수 있습니까?
지금까지의 솔루션:
>>> json_string = '{"last_updated": {"$gte": "Thu, 1 Mar 2012 10:00:49 UTC"}}'
>>> dct = json.loads(json_string, object_hook=datetime_parser)
>>> dct
{u'last_updated': {u'$gte': datetime.datetime(2012, 3, 1, 10, 0, 49)}}
def datetime_parser(dct):
for k, v in dct.items():
if isinstance(v, basestring) and re.search("\ UTC", v):
try:
dct[k] = datetime.datetime.strptime(v, DATE_FORMAT)
except:
pass
return dct
object_hook 사용에 대한 자세한 내용은 JSON 인코더 및 디코더
API로 됩니다.Json은 GET REST API로 하겠습니다. 취득수 .__date__
DATE_FORMATE, JSON, DATE_FORMAT.
DATE_FORMAT = '%a, %d %b %Y %H:%M:%S UTC'
정규식 패턴은 아마도 더 다듬어야 할 것입니다.
PS: 혹시 궁금하신지 모르겠지만 json_string은 MongoDB/PyMongo 쿼리입니다.
object_hook을 전달해야 합니다.매뉴얼에서 다음 항목을 참조하십시오.
object_hook은 임의의 오브젝트 리터럴 디코딩 결과(dict)로 호출되는 옵션 함수입니다.dict 대신 object_hook 반환값이 사용됩니다.
다음과 같이 합니다.
import datetime
import json
def date_hook(json_dict):
for (key, value) in json_dict.items():
try:
json_dict[key] = datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S")
except:
pass
return json_dict
dumped_dict = '{"debug": false, "created_at": "2020-08-09T11:24:20"}'
loaded_dict = json.loads(dumped_dict, object_hook=date_hook)
타임존도 취급하고 싶다면 strptime 대신 dateutil을 사용해야 합니다.
Nicola가 제안한 대로 다음 두 가지 변경 사항을 적용합니다.
dateutil.parser
datetime.datetime.strptime
- 이치노으로 어떤 것을 것이 .
except:
또는 코드:
import dateutil.parser
def datetime_parser(json_dict):
for (key, value) in json_dict.items():
try:
json_dict[key] = dateutil.parser.parse(value)
except (ValueError, AttributeError):
pass
return json_dict
str = "{...}" # Some JSON with date
obj = json.loads(str, object_hook=datetime_parser)
print(obj)
기술적으로 오브젝트 후크 기능을 제공하는 것만으로 동작하지만 프레임워크 개발자가 의도한 적절한 서브클래스를 사용하는 것이 좋습니다.
class _JSONDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
json.JSONDecoder.__init__(
self, object_hook=self.object_hook, *args, **kwargs)
def object_hook(self, obj):
ret = {}
for key, value in obj.items():
if key in {'timestamp', 'whatever'}:
ret[key] = datetime.fromisoformat(value)
else:
ret[key] = value
return ret
완전성을 위해 디코더에 대응하는 커스텀 JSONEncoder를 다음에 나타냅니다.
class _JSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (datetime.date, datetime.datetime, pd.Timestamp)):
return obj.isoformat()
return json.JSONEncoder.default(obj)
둘 다 다음과 같이 동작합니다.
json_str = json.dumps({'timestamp': datetime.datetime.now()}, cls=_JSONEncoder)
d = json.loads(json_str, cls=_JSONDecoder)
질문 내용으로는 문자열이 날짜 값임을 알 수 없습니다.이는 다음 문자열의 예를 포함하는 json의 설명서와 다릅니다.
'{"__complex__": true, "real": 1, "imag": 2}'
."__complex__": true
데이터 유형을 추론하는 데 사용할 수 있지만, 이러한 표시기가 없는 한 문자열은 문자열일 뿐이며, 모든 문자열을 반복 검색하여 날짜로 표시되는지 여부를 판별할 수 있습니다.
이 경우 스키마를 사용할 수 있는 경우 스키마를 사용해야 합니다.
다음과 같이 regex를 사용하여 특정 필드를 날짜/시간으로 변환할지 여부를 결정할 수 있습니다.
def date_hook(json_dict):
for (key, value) in json_dict.items():
if type(value) is str and re.match('^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d*$', value):
json_dict[key] = datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f")
elif type(value) is str and re.match('^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$', value):
json_dict[key] = datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S")
else:
pass
return json_dict
다음으로 콜의 object_hook 파라미터를 사용하여 date_hook 함수를 json.loads()로 참조할 수 있습니다.
json_data = '{"token": "faUIO/389KLDLA", "created_at": "2016-09-15T09:54:20.564"}'
data_dictionary = json.loads(json_data, object_hook=date_hook)
메서드는 날짜-시간 형식의 재귀 문자열 검색을 구현합니다.
import json
from dateutil.parser import parse
def datetime_parser(value):
if isinstance(value, dict):
for k, v in value.items():
value[k] = datetime_parser(v)
elif isinstance(value, list):
for index, row in enumerate(value):
value[index] = datetime_parser(row)
elif isinstance(value, str) and value:
try:
value = parse(value)
except (ValueError, AttributeError):
pass
return value
json_to_dict = json.loads(YOUR_JSON_STRING, object_hook=datetime_parser)
제가 알기로는 바로 사용할 수 있는 솔루션은 없습니다.
먼저, 솔루션은 문자열과 데이터를 올바르게 구별하기 위해 json 스키마를 고려해야 합니다.어느 정도 json schema inferencer(json schema inferencer github의 google)를 사용하여 스키마를 추측하고 실제 날짜인 장소를 수정할 수 있습니다.
스키마를 알고 있다면 json을 해석하고 문자열 표현을 datetime으로 대체하는 함수를 만드는 것이 매우 쉬울 것입니다.코드에 대한 영감을 유효한 제품에서 찾을 수 있을 것입니다(json 스키마 검증도 좋은 아이디어일 수 있습니다).
Nicola의 답변에 영감을 받아 python3(기본값이 아닌 str)에 맞게 조정:
import re
from datetime import datetime
datetime_format = "%Y-%m-%dT%H:%M:%S"
datetime_format_regex = re.compile(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$')
def datetime_parser(dct):
for k, v in dct.items():
if isinstance(v, str) and datetime_format_regex.match(v):
dct[k] = datetime.strptime(v, datetime_format)
return dct
이를 통해 시행/예외 메커니즘을 사용할 필요가 없습니다.OP 테스트 코드:
>>> import json
>>> json_string = '{"debug": false, "created_at": "2020-08-09T11:24:20"}'
>>> json.loads(json_string, object_hook=datetime_parser)
{'created_at': datetime.datetime(2020, 8, 9, 11, 24, 20), 'debug': False}
와 " " "datetime_format
변수를 다른 패턴(예: 중간에 T가 없는 경우)에 맞게 쉽게 조정할 수 있습니다.
isoformat(따라서 마이크로초와 함께 저장됨)에 저장된 문자열을 datetime 개체로 다시 변환하려면 다음 질문을 참조하십시오.
JSON 인코더 및 디코더 작성을 제안하는 솔루션은 모두 완전히 유효합니다.여기서 볼 수 있는 유일한 문제는 퍼포먼스에 약간의 영향을 주는 것입니다.이는 각 JSON 값을 스캔하여 날짜/시간 형식과 일치하는지 확인하는 경우에 발생할 수 있습니다.
여기 dataclass-wizard 라이브러리를 사용하는 방법이 있습니다(참고: API 응답에 대해 실제로 작동하도록 설계되어 있습니다).
포함된 CLI 유틸리티를 사용하여 JSON 응답을 데이터 클래스 스키마로 변환합니다.「」의 .
debug
되어 있기 저는 전달하고 .-f
파이썬 불그렇지 않으면 다음과 같이 표시됩니다.Union[bool, str]
디폴트 유추 타입입니다.$ echo '{"debug": "false", "created_at": "2020-08-09T11:24:20"}' | wiz gs -f
상단의 Import를 포함한 출력(표시되지 않음):
@dataclass class Data(JSONWizard): """ Data dataclass """ debug: bool created_at: datetime
이제 위의 샘플 JSON 문자열을 디시리얼라이즈하여
Data
물건.주의:created_at
로서 와야 한다datetime
type. 에 대한 값도 비슷합니다.debug
, 이것은 다음과 같이 디코딩해야 합니다.bool
.string = """{"debug": "false", "created_at": "2020-08-09T11:24:20"}""" c = Data.from_json(string) print(repr(c))
JSON에 다시 연재합니다.그
datetime
개체를 다시 변환해야 합니다.
문자열:print(c.to_json()) # {"debug": false, "createdAt": "2020-08-09T11:24:20"}
대부분의 경우, 이것은 쌍방향의 문제로, 커스텀 인코더를 사용하는 경우는 커스텀 디코더를 사용하는 것이 좋습니다(그 반대의 경우도 있습니다).이 경우 디코더는 인코딩된 데이터를 해석하여 원래 json 개체를 반환할 수 있어야 합니다.
아래에는 2가지 다른 전략을 사용하여 python 비직렬화 객체를 json으로 변환하기 위한 full excires가 있습니다.
- 클래스를 직렬화하기 위해 "json" 메서드를 구현하는 클래스에 JSONEncoder 클래스를 serializa에 패치합니다.
- "Converters" 메서드 목록을 사용하여 특정 파이썬 유형을 직렬화합니다.
다음 예에서는 {enum.name:enum.value}dict로 커스텀json 메서드를 사용하여 Enun.value 오브젝트는 python(날짜 및 tuple)으로 시리얼화 할 수 없습니다.이러한 타입을 시리얼화 가능한 타입으로 변환할 수 있습니다.
부호화가 완료되면 custom_json_decoder 메서드를 호출하여 해당 json을 python 원시 유형으로 되돌릴 수 있습니다.다음 스크립트는 모두 완료되었으며 "있는 그대로" 실행됩니다.
from enum import Enum
from dateutil.parser import parse as dtparse
from datetime import datetime
from datetime import date
from json import JSONEncoder
from json import loads as json_loads
from json import dumps as json_dumps
def wrapped_default(self, obj):
json_parser = getattr(obj.__class__, "__json__", lambda x: x.__dict__)
try:
return json_parser(obj)
except Exception:
return wrapped_default.default(obj)
wrapped_default.default = JSONEncoder().default
JSONEncoder.default = wrapped_default
CONVERTERS = {
"datetime": dtparse,
"date": lambda x: datetime.strptime(x, "%Y%m%d").date(),
"tuple": lambda x: tuple(x),
}
class RskJSONEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, date):
return {"val": obj.strftime("%Y%m%d"), "pythontype": "date"}
elif isinstance(obj, datetime):
return {"val": obj.isoformat(), "pythontype": "datetime"}
elif isinstance(obj, tuple):
return {"val": list(obj), "pythontype": "tuple"}
return super().default(obj)
def custom_json_decoder(obj):
def json_hook(json_obj):
try:
return CONVERTERS[json_obj.pop("pythontype")](json_obj["val"])
except Exception:
res = json_obj
return res
return json_loads(obj, object_hook=json_hook)
def custom_json_encoder(obj):
return json_dumps(obj, cls=RskJSONEncoder)
if __name__ == "__main__":
class Test(Enum):
A = date(2021, 1, 1)
B = ("this", " is", " a", " tuple")
def __json__(self):
return {self.name: self.value}
d = {"enum_date": Test.A, "enum_tuple": Test.B}
this_is_json = custom_json_encoder(d)
this_is_python_obj = custom_json_decoder(this_is_json)
print(f"this is json, type={type(this_is_json)}\n", this_is_json)
print(
f"this is python, type={type(this_is_python_obj)}\n",
this_is_python_obj,
)
django json 살균기를 찾는 경우:
from django.utils.timezone import now
from django.core.serializers.json import DjangoJSONEncoder
from django.utils.dateparse import parse_datetime
dt = now()
sdt = json.dumps(dt.strftime('%Y-%m-%dT%H:%M:%S'))
ndt = parse_datetime(json.loads(sdt))
print(sdt)
# "2022-04-27T12:20:23"
print(ndt)
# 2022-04-27 12:20:23
언급URL : https://stackoverflow.com/questions/8793448/how-to-convert-to-a-python-datetime-object-with-json-loads
'programing' 카테고리의 다른 글
JSONC가 뭐죠?JSONC와 JSON-C는 다른가요? (0) | 2023.03.05 |
---|---|
각도 JS 필터가 동일하지 않음 (0) | 2023.03.05 |
Form Data와 jQuery#serialize()의 차이점 (0) | 2023.02.28 |
Gatsby JS, Restful API에서 데이터 가져오기 (0) | 2023.02.28 |
created_at 컬럼에 ID가 자동으로 생성되는 것처럼 생성 날짜/시간을 자동으로 생성하도록 하려면 어떻게 해야 합니까? (0) | 2023.02.28 |