24.01.24

서린·2024년 1월 24일

혼자개발

목록 보기
27/82

어제 났던 에러
com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 8 path $

해결방법을 서칭하는 중이다

MalformedJsonException 에러는
Restful api를 지원하는 서버와 통신하기 위해 gson을 사용하는 경우에 발생 할 수있고
발생한 이유는 gson에서 json을 처리할 때 json 형식의 RFC 4627을 엄격하게 지키지 않아서라는데 (json data에 불필요한 값이나 띄어쓰기가 있는 경우 등등)
해결방법은

  • server에서 json형식을 규격에 맞게 고치기
  • setLenient()를 사용하기
    이렇게 두가지 정도라고한다

다른 사람들이 규격을 어긴 예시를 보면 끝에 ,를 붙였다든지 하는 것들이었는데, 나는 꼼꼼히 찾아봐도 보이지 않아서 setLenient()를 사용해보려고 한다

또 다른 곳에서 본 에러의 이유!
외부 API에서 받은 JSON 데이터가 올바른 형식이 아니거나 손상되었을 때, 
일반적으로 Gson은 엄격한 JSON 파싱을 수행하는데
이때 JSON 데이터가 완벽하게 형식에 맞지 않으면 Gson이 파싱을 거부하고 'MalformedJsonException'과 같은 예외를 던질 수 있다
그러나 실제 상황에서는 외부 API에서 받은 JSON 데이터가 항상 완벽하게 형식에 맞지 않을 수 있는일(API 응답이 부분적으로 손상되었거나, 예상하지 못한 문자열이 포함)이 많은데,
이런 경우, 'JsonReader.setLenient(true)'를 호출하여 JsonReader 객체를 설정하면 Gson은 보다 관대하게 JSON 데이터를 파싱하고, 형식에 맞지 않는 부분을 무시하고 파싱을 진행한다

ApiParseContoller의 윗 부분은 생략하고, json 파싱 부분만 보자면

// jsonParser를 사용해서 string 값을 json객체로 만들어준다
JsonParser parser = new JsonParser();
JsonReader reader = new JsonReader(new StringReader(sb.toString()));
reader.setLenient(true);
// 만들어진 json객체는 jsonObject클래스를 사용해서 저장된다
JsonObject obj = parser.parse(reader).getAsJsonObject();

JsonObject responseBody = obj.getAsJsonObject("response").getAsJsonObject("body");
if (responseBody != null) {
    JsonArray items = responseBody.getAsJsonObject("items").getAsJsonArray("item");

    for (JsonElement jsonElement : items) {
        JsonObject temp = jsonElement.getAsJsonObject();

        String mtName = temp.has("frtrlNm") ? temp.get("frtrlNm").getAsString() : "";
        String mtLocation = temp.has("addrNm") ? temp.get("addrNm").getAsString() : "";
        int mtHeight = temp.has("aslAltide") ? temp.get("aslAltide").getAsInt() : 0;


        Mountain mountain = Mountain.builder()
                .mtName(mtName)
                .mtLocation(mtLocation)
                .mtHeight(mtHeight)
                .build();
        }
    }

JsonParser parser = new JsonParser();

  • JsonParser 인스턴스 생성
  • JSON 데이터를 파싱하는 메소드를 제공하는 GSON 라이브러리의 클래스
  • Json문자열을 JsonObject, JsonArray, JsonPrimitive, 기타 GSON 유형의 계층구조로 파싱 하는데에 사용된다

JsonReader reader = new JsonReader(new StringReader(sb.toString()));

  • JsonReader 인스턴스 생성
  • Gson라이브러리의 또 다른 클래스
  • 스트리밍 json parser

reader.setLenient(true);

  • JsonReader instance에 대한 메소드 호출
  • lenient를 true로 설정한 것 = json parser가 json을 파싱할 때 더 허용적일것이라는 의미
  • MalformedJsonException을 발생시키는 몇 가지 JSON 파싱 문제를 허용할 수 있다

JsonObject obj = parser.parse(reader).getAsJsonObject();

  • 실제로 json데이터를 파싱 한다

이 코드들을 실행시키면 또 다른 500에러가 난다

0개의 댓글