파이썬 컴파일시 에러:: 'TypeError: Object of type int64 is not JSON serializable' ///백준 문제 : 자연수 뒤집어 배열로 만들기 풀이

권수민·2023년 8월 28일
1

백준 문제를 풀다가 풀이를 여러가지 다른 코드를 시도해보는데
reversed사용시 TypeError: Object of type int64 is not JSON serializable 가 나오면서 컴파일링이 안되는데,
이를 알아보기 위해 reversed()타입에 대해 찾아보았다.

reversed()
=> <<reversed object at 0x7f7ac6b7a170>>를 반환하기에, type()해서 보니 <class 'reversed'>를 반환한다.

이러한 타입을 바로 대입해 버려서 생겨났던 에러였는데, list(reversed())로 반환해 리턴하니 잘 되었다..젠장 멍청한 실수. 이래서 함수의 반환값과 객체에 대해 알아두어야 쉽게 에러를 찾을 수 있는 것 같다.

문제 설명
자연수 n을 뒤집어 각 자리 숫자를 원소로 가지는 배열 형태로 리턴해주세요. 예를들어 n이 12345이면 [5,4,3,2,1]을 리턴합니다.
제한 조건
n은 10,000,000,000이하인 자연수입니다.



answer = []
def solution(n):
    ## answer = [] #여기다 놓으면 계속 리스트가 비어진다. 전역변수로 바꿔야해
    if n <= 10000000000 and n > 0:
        i = n % 10
        answer.append(i)
        if n >= 10:
            solution(n//10)
    return answer
       
        
    ##새로운 다른 코드 => reversed()사용안하고 
    def solution(n):
        # string = str(n)
        # for i in range(len(string),0,-1): #12345면 길이 5개부터 -1해서 1까지 돈다
        #     integer = int(string[i-1])
        #     answer.append(integer)
        # return string #answer
        
    ##새로운 다른 코드  => reverse()사용 
    def solution(n):
        ## answer = reversed(str(n)) 이렇게 해버리면 도출된 값 <메모리주소가> answer이 되기떄문에 type reversed 가 되어 받지를 못하는것이고
        ## return list(reversed(str(n)) 이렇게 하면 -> str 이 나와 int로 바꿔줘야돼.
        # return list(map(int, reversed(str(n))))
        ##reversed()의 객체 자체는 이터레이블이기 떄문에 list없이 매개변수로 가능
        
   ##새로운 다른 코드
    def solution(n):
        # return [int(i) for i in str(n)][::-1] 
        ## [::-1]슬라이싱을 사용하여 역행
        ## 아래는 테스트로 출력해 보기 위한 코드입니다.
        ## print("결과 : {}".format(solution(12345)))
                     
                     

이런 이유 외의 typeerror가 난 이유를 찾아보았다.

다른이유

json이란?/그외의 파이썬 <-> json 데이터 변환 과정 ::https://velog.io/@stella_k/json%EC%9D%B4%EB%9E%80-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%8C%8C%EC%9D%B4%EC%8D%AC%EA%B3%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EB%B3%80%EA%B2%BD%ED%95%98%EA%B3%A0-%EB%B3%80%EA%B2%BD%EB%B0%9B%EB%8A%94%EC%A7%80loadsdata

API와 통신을 자주하게 된다면 json모듈을 많이 이용하게되는데, json모듈이 알아들을 수 없는 형태?들이 있다.

대표적으로 날짜.시간 타입을 곧이 곧대로 넣을때 생기는 에러인데,

import datetime, json

today = datetime.date.today()
data = {'date': today}

json_data = json.dumps(data) 
#=> TYPE ERROR :: not JSON serializable

문자열로 바꿔주면 문제는 없지만 (strftime()으로 값을 문자열로 바꿔줌)

import datetime, json

today = datetime.date.today()
data = { 'date': today.strftime('%Y-%m-%d')}

json_data = json.dumps(data)

매번 이러한 에러들을 하나하나 손볼 수 없기 때문에 다른 새로운 방법을 소개해보겠다.

default 로 보내 예외처리하기

default 함수를 지정해서 type error시의 대처방법을 집어넣는것이다.

마치 전에 쓴 try와 except구문과 비슷한 방법이지만 json형태로 소통하는 것이기에 구조가 좀 다르다.

try except 구문 :: https://velog.io/@stella_k/python-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC-tryexcept-%EC%8B%AC%ED%99%94

import datetime
import json

def json_default(value):
    if isinstance(value, datetime.date):
        return value.strftime('%Y-%m-%d')
    elif isinstance(value, reversed):
        return list(value)  # reversed 객체를 리스트로 변환
	raise TypeError(f'Object of type {type(value).__name__} is not JSON serializable')
    
    
data1 = {'date': datetime.date.today()}
data2 = {'reversed_data': reversed([1, 2, 3, 4])}

json_data1 = json.dumps(data1, default=json_default)
json_data2 = json.dumps(data2, default=json_default)

print(json_data1)  # 예: {"date": "2023-08-26"}
print(json_data2)  # {"reversed_data": [4, 3, 2, 1]}

먼저 json_default(value)라는 메소드를 만들어 예외처리를 해줄 것인데, json.dumps() 메서드는 이 json_default 함수를 사용하여 기본적으로 JSON 시리얼라이즈가 불가능한 객체(value)를 만났을 때 어떻게 처리할지 결정합니다.

def json_default(value):

>>>>>>>>>>>>

json_data2 = json.dumps(data2, default=json_default)

여기서 예외처리는 elif를 통해 조건을 더 붙혀 줄 수 있다.
그래서 나는 reversed()형태 그대로 list()없이 소통하게 더해주었다.

먼저 isinstance(객체, 클래스 또는 데이터 타입)의 형태를 가지고있다. 즉 첫번쨰 인자 객체는 내가 에러시 맞게 바꿔줄 객체를 넣고, 두번쨰 인자에 그 데이터의 클래스나 데이터 타입을 적어 맞는 클래스나 타입인지를 확인하는것이다.
=>받은 딕셔너리형태의 데이터의 value값이 reversed가 맞는지
=> reversed()형태 x

그리하고 나면 그 것을 알맞게 바꿔줄 코드를 실행하고, 그 외의 것이면 예외처리를 하지 않고 에러처리해주겠다라고 하는것.

 elif isinstance(value, reversed):
 	return list(value)  # reversed 객체를 리스트로 변환
    
 raise TypeError('not JSON serializable')
 #조건 외의 에러는 에러를 나타내라는 것이다.
 #근데 어디부분이 에러인지 확인하기 어렵기 때문에 더 자세히 구체적인 원인을 나타내기위해 이렇게 고쳐주는게 좋다.
 
 raise TypeError(f'Object of type {type(value).__name__} is not JSON serializable')

그리고 이렇게 보내줄 데이터를 꼭 딕셔너리 형태로 써줘야한다.

data2 = {'reversed_data': reversed([1, 2, 3, 4])}

그 이후에 위에 언급한 json.dupms()를 통해 딕셔너리 형태의 데이터를 넣고, 두번쨰 인자로 default값을 정해준다.

json_data2 = json.dumps(data2, default=json_default)

print(json_data2)  # {"reversed_data": [4, 3, 2, 1]}

이 방식을 reversed()만 예외로 처리하여 두 함수로 만들어 표현하면::

import json

def json_default(value):
    if isinstance(value, reversed):  # reversed 객체인지 확인
        return list(value)  # reversed 객체를 리스트로 변환
    raise TypeError('not JSON serializable')

def solution(n):
    answer = reversed(str(n))
    data = {"reversed_data": answer}
    json_data = json.dumps(data, default=json_default)
    return json_data

print(solution(1234))  # 출력: {"reversed_data": ["4", "3", "2", "1"]}
profile
초보개발자

0개의 댓글