[Android/Issue] MalformedJsonException

이도연·2023년 9월 15일
0

trouble shooting

목록 보기
7/12
  • Issue

retrofit 으로 api 를 호출거나 데이터를 받아오던 중 오류가 자주 발생한다.
나의 경우 앱이 중지되었고, logcat 확인 결과 에러 문구는 아래와 같았다.

MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $

MalformedJsonException 은 Retrofit과 Gson을 사용하여 서버로부터 JSON 데이터를 파싱할 때 발생할 수 있는 예외다.



var gson= GsonBuilder().setLenient().create()

val retrofit= Retrofit.Builder()
        .baseUrl("https://openapi.foodsafetykorea.go.kr/")
        .addConverterFactory(GsonConverterFactory.create(gson))
        .client(okHttpClient)
        .build()

난, 맨 위의 코드를 적용했다.


원인은

  1. JSON 데이터가 제대로 분석되지 않았거나,
  2. 서버로부터 수신한 JSON 데이터가 기대한 형식을 따르지 않거나,
  3. 예상하지 않은 문자 또는 구조적 오류가 있을 때 발생하며, JSON 형식 규칙을 준수하면 된다.

서버 측에서 JSON 데이터를 잘못 생성하거나, 데이터 전송 중에 손상되었을 수도 있다. 이때는 키 값을 다시 가져와 시도해보는 방법도 있다. (Encoding/Decoding)

setLenient(true) 이 메서드는 Gson 구문 분석범위를 관대하게 만든다.
즉, JSON 데이터가 약간의 구문 오류나 형식을 위배해도, 무시하고 분석을 계속하도록 허용한다. 이것은 JSON 데이터가 서버에서 예상대로 포맷되지 않았을 때 유용하다.




  • 해결
  1. setLenient(true) 사용
    이 방법은 JSON 데이터에 약간의 오류가 있더라도 무시하고 구문 분석을 계속할 수 있도록 Gson을 설정한다. 그러나 JSON 데이터의 유효성을 보장할 수 없다. 따라서 본질적인 해결법은 아님.

  1. JsonReader를 직접 제어
    setLenient(true) 대신 JsonReader를 직접 제어하여 문제가 있는 부분을 무시하거나 수정할 수 있다. 더 정교하지만 코드는 복잡해질 수 있습니다.




난 1번을 사용하여 해결했다.

setLenient(true) 사용 시 올바르지 않은 JSON 데이터가 무시되고 파싱이 계속된다. JSON 데이터가 중요한 경우 추천하지 않는다.
가능한 경우 서버 측에서 JSON 데이터의 유효성을 확인하고 수정하는 것이 가장 좋다.

StackOverFlow 를 서치한 결과, 잘못된 header 를 사용했거나, JSON 이 아닌 다른 형태로 전달받은 것이 원인일 수도 있다. 그렇다면 플랫폼에서 서버요청이 제대로 이루어지는지, 결과값이 다른 형태는 아닌지 확인해야한다.



before

private val dustRetrofit = Retrofit.Builder()
        .baseUrl(DUST_BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .client(
            createOkHttpClient()
        ).build()

after

private val dustRetrofit = Retrofit.Builder()
        .baseUrl(DUST_BASE_URL)
        .addConverterFactory(GsonConverterFactory.create(GsonBuilder().setLenient().create()))
        .client(
            createOkHttpClient()
        ).build()







0개의 댓글