Maria DB Data Type Error 해소 방법 공유 - smilebulee/infogen_ims GitHub Wiki

Maria DB 연동시 테이블 컬럼타입이 Date타입이고, 해당 일이 실제 Date 형식으로 값이 넘어오는 경우, Type Error가 발생.
Date 값이 datetime.date(YYYY, MM, DD) 패턴으로 리턴되는데, datetime.date 를 json으로 파싱하는 과정에서 Error가 발생함.

Exception Log

Traceback (most recent call last):
  File "/root/.local/lib/python3.6/site-packages/flask/app.py", line 2464, in __call__
    return self.wsgi_app(environ, start_response)
  File "/root/.local/lib/python3.6/site-packages/flask/app.py", line 2450, in wsgi_app
    response = self.handle_exception(e)
  File "/root/.local/lib/python3.6/site-packages/flask_restful/__init__.py", line 272, in error_router
    return original_handler(e)
  File "/root/.local/lib/python3.6/site-packages/flask/app.py", line 1867, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/root/.local/lib/python3.6/site-packages/flask/_compat.py", line 38, in reraise
    raise value.with_traceback(tb)
  File "/root/.local/lib/python3.6/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/root/.local/lib/python3.6/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/root/.local/lib/python3.6/site-packages/flask_restful/__init__.py", line 272, in error_router
    return original_handler(e)
  File "/root/.local/lib/python3.6/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/root/.local/lib/python3.6/site-packages/flask/_compat.py", line 38, in reraise
    raise value.with_traceback(tb)
  File "/root/.local/lib/python3.6/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/root/.local/lib/python3.6/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/root/.local/lib/python3.6/site-packages/flask_restful/__init__.py", line 472, in wrapper
    return self.make_response(data, code, headers=headers)
  File "/root/.local/lib/python3.6/site-packages/flask_restful/__init__.py", line 501, in make_response
    resp = self.representations[mediatype](data, *args, **kwargs)
  File "/root/.local/lib/python3.6/site-packages/flask_restful/representations/json.py", line 21, in output_json
    dumped = dumps(data, **settings) + "\n"
  File "/usr/lib/python3.6/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/usr/lib/python3.6/json/encoder.py", line 201, in encode
    chunks = list(chunks)
  File "/usr/lib/python3.6/json/encoder.py", line 428, in _iterencode
    yield from _iterencode_list(o, _current_indent_level)
  File "/usr/lib/python3.6/json/encoder.py", line 325, in _iterencode_list
    yield from chunks
  File "/usr/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict
    yield from chunks
  File "/usr/lib/python3.6/json/encoder.py", line 437, in _iterencode
    o = _default(o)
  File "/usr/lib/python3.6/json/encoder.py", line 180, in default
    o.__class__.__name__)
TypeError: Object of type 'date' is not JSON serializable



app.py 소스 내 다음 소스 추가. 1

import datetime
from json import JSONEncoder

class DateTimeEncoder(JSONEncoder):
    # Override the default method
    def default(self, obj):
        if isinstance(obj, (datetime.date, datetime.datetime)):
            return obj.isoformat()

app.py 소스 내 다음 소스 추가. 2

    // 실제 app.py에서 retrun 시켜주는 구문에 위 선언한 class 적용.
    기존   : return result2
    변경후 : json.dumps(result2, indent=4, cls=DateTimeEncoder)

class wrkTimeInfoByEml(Resource): # Mariadb 연결 진행
    def get(self):

        data = request.get_json()

        logging.debug('================== App Start ==================')
        logging.debug(data)
        logging.debug(data["email"])
        logging.debug('================== App End ==================')

        #requirements pymysql import 후 커넥트 사용
        mysql_con = pymysql.connect(host='218.151.225.142', port=3306, db='IFG_IMS', user='ims2', password='1234',
                                        charset='utf8')
        try:
            with mysql_con.cursor(pymysql.cursors.DictCursor) as cursor:
                #쿼리문 실행
                sql = "SELECT * FROM TB_WRK_TM_MGMT_M WHERE EMP_EMAL_ADDR = '" + data["email"] + "'"
                logging.debug(sql)
                cursor.execute(sql)

        finally:
            mysql_con.close()

        result2 = cursor.fetchall()
        for row in result2:
            logging.debug('====== row====')
            logging.debug(row)
            logging.debug('===============')
        array = list(result2)  # 결과를 리스트로
        
        # return result2
        return json.dumps(result2, indent=4, cls=DateTimeEncoder)    //indent Option은 로그확인시 들여쓰기 적용으로 파라미터 식별이 편하도록 하는 옵션.

    하지만 기존 result2 로깅시 [{'param':'value'}...] 형태로 출력되나,
    json.dumps 적용 후 로깅시 [{"param":"value"}...] 형태로 출력된다. (Single Quete --> Double quote)
    이 경우, Web Html 에서 데이터출력의 형태가 변경되므로 views.py에서 변환처리 한다.

views.py 소스 내 다음 소스 추가. 1

import ast

views.py 소스 내 다음 소스 추가. 2

    // 실제 views.py에서 retrun 시켜주는 구문 변경
    기존   : return JsonResponse(r.json(), safe=False)
    변경후 : return JsonResponse(ast.literal_eval(r.json()), safe=False)

def getWrkTimeInfoByEml(request):
    param = json.loads(request.GET['param'])

    logger.info("Parameters Start")
    logger.info(param)
    logger.info("Parameters End")

    # api 호출
    r = requests.get('http://dili_api:5006/wrkTimeInfoByEml', json=param)
    logger.info(r)
    logger.info(r.text)
    logger.info(logger.info(ast.literal_eval(r.json())))
    logger.info(json.loads(r.text))
    # return JsonResponse(r.json(), safe=False)
    return JsonResponse(ast.literal_eval(r.json()), safe=False)
⚠️ **GitHub.com Fallback** ⚠️