Programming/Python

python json 모듈 사용시 not JSON serializable 에러를 피하는 방법

동건 2016. 12. 12. 23:29

웹 기반 python 코드를 짜다 보면, 특히 다른 쪽 API와 통신을 자주 하게 된다면 json 모듈을 많이 이용하게 된다. python이 기본적으로 지원하는 데이터 타입인 list와 dictionary 구조를 유지한 채 json 형식으로 바꿔주고, 그 반대로 json 문자열을 해독해서 python 데이터 타입으로 바꿔주는 역할을 하는 것이 python의 json 모듈이다.


import json
data = {'key': ['value1', 'value2']}
json_data = json.dumps(data) # json string from python data

python_data = json.loads(json_data) # get python data back from json string
assert data == python_data

그런데 json.dumps 과정에서 json 모듈이 알아들을 수 없는 것들이 들어가는 경우가 종종 있다. 가장 대표적인 예가 바로 python 날짜/시간 타입을 곧이 곧대로 넣었을 경우이다.


import datetime, json
today = datetime.date.today()
data = { 'date': today}
json_data = json.dumps(data) # TYPE ERROR :: not JSON serializable

today 라는 날짜 변수를 json 모듈이 어찌해야 할 지 모르는 경우이다. 물론 다음과 같이 날짜 변수를 문자열로 잘 바꿔주면 문제는 없을 것이다.


import datetime, json
today = datetime.date.today()
data = { 'date': today.strftime('%Y-%m-%d')}
json_data = json.dumps(data)

근데 내가 에러가 없도록 일일이 예상해서 코딩으로 해결할 수는 없다. 따라서 에러가 났을 시의 대처법을 json 모듈에게 알려줄 수 있는 방법을 소개한다. 바로 default 함수를 지정해서 type error 시 대처 방법을 집어넣는 것이다.


import datetime, json

def json_default(value):
  if isinstance(value, datetime.date):
    return value.strftime('%Y-%m-%d')
  raise TypeError('not JSON serializable')
data = {'date': datetime.date.today()}
json_data = json.dumps(data, default=json_default)

에러가 나지 않고 잘 변환된 것을 확인할 수 있을 것이다. 간단히 원리를 설명해보겠다. 기본적으로 json 모듈은 data를 받아서 그 데이터 구조를 따라 iteration을 돌면서 내부 value들을 json string으로 변환하려고 할 것이다. 그 와중에 date 타입 변수가 끼어들면서 당장 문자열로 변환할 수 없게 되면서 Type Error를 내는 것이다. default로 내가 함수를 지정해 놓았다면, 이 순간 문제를 일으키는 value를 가지고 default 함수에 던져서 해결할 수 있는 건 해결하는 것이다. 나는 date 타입일 경우 어떻게 처리하는 지에 대한 예를 들었고, 그 외에 내가 다른 여러 유형의 데이터를 이용한다면 각 경우에 따른 대처법을 모두 등록할 수 있을 것이다.

참고로 자신이 처리하고자 하는 경우를 다 코딩한 후에, 즉 if elif 구문을 다 쓴 후 그 외의 경우에는 에러를 띄우도록 하는 것이 바람직하다. 본인의 코딩으로 커버가 안되는 사태가 발생한다면 default 함수는 에러를 띄워서 사용자에게 알려줘야 할까 / 슬쩍 넘어가야 할까?

반응형