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()
난, 맨 위의 코드를 적용했다.
원인은
서버 측에서 JSON 데이터를 잘못 생성하거나, 데이터 전송 중에 손상되었을 수도 있다. 이때는 키 값을 다시 가져와 시도해보는 방법도 있다. (Encoding/Decoding)
setLenient(true)
이 메서드는 Gson 구문 분석범위를 관대하게 만든다.
즉, JSON 데이터가 약간의 구문 오류나 형식을 위배해도, 무시하고 분석을 계속하도록 허용한다. 이것은 JSON 데이터가 서버에서 예상대로 포맷되지 않았을 때 유용하다.
setLenient(true)
사용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()