2024-04-30T17:39:42.068+09:00 WARN 28110 --- [io-8080-exec-10] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Cannot invoke "com.zetawayv.mobby.domain.route.dtos.RouteCreateResponseDto.getGeoJson()" because "this.data" is null]
TMAP 도보 길찾기 API 호출시 생긴 오류입니다.
이 에러는 HttpMessageNotWritableException으로 표시되며, JSON으로 객체를 변환하는 동안에 발생한 문제를 나타냅니다. 구체적으로는 RouteCreateResponseDto 객체에서 getGeoJson() 메서드를 호출할 때 this.data가 null이라는 오류가 발생했습니다.
우선 이 문제를 해결하기 위해 Response가 어떻게 나오는지 보겠습니다.
API 호출은 잘 되지만, 담아오는 DTO에 매치할 수 없어서 담아오지 못하는 것으로 우선 파악했습니다.
여러 시도 끝에 해결 방법을 다음과 같이 찾았습니다.
spring:
mvc:
converters:
preferred-json-mapper: gson
(여담이지만 야물파일이라고 읽는게 이상한가요..ㅋ 아는 언니가 제가 야물야물거리는게 귀엽다고 하는데 이게 왜 귀여운지 잘 모르겠음.)
Json을 읽어오는 과정에서 오류가 있어서, Json을 읽어 올 수 있는 컨버터를 장착해줍니다.
버전따라 다르다고 하는데 저는 Spring Boot 3.1.4 를 사용하기 때문에 저렇게 설정을 해줬습니다.
뭐지 기준이 2.7인가 그랬습니다.
@Getter
@RequiredArgsConstructor
private static class RouteCreateResponseImpl extends RouteCommonResponse implements RouteCreateResponse {
private RouteCreateResponseDto data;
@Override
public Integer getStatusCode(){
return super.statusCode;
}
@Override
public String getMsg(){
return super.msg;
}
@Override
public RouteCreateResponseDto getOriginalData() {
return data;
}
@Override
public Integer getTotalDistance() {
return data.getGeoJson().getFeatures().getFirst().getProperties().getTotalDistance();
}
@Override
public Integer getTotalTime() {
return data.getGeoJson().getFeatures().getFirst().getProperties().getTotalTime();
}
}
나는 기존에 이렇게 코드를 작성했는데, 그냥 다음과 같이 받아오는 것으로 수정했습니다.
@Getter
@Setter
@RequiredArgsConstructor
private static class RouteCreateResponseImpl implements RouteCreateResponse {
private String type;
private List<FeatureDto> features;
그래도 다음과 같은 오류가 발견되었습니다.
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.ArrayList<java.lang.Double>` from Floating-point value (token `JsonToken.VALUE_NUMBER_FLOAT`)
at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 134] (through reference chain: com.zetawayv.mobby.infrastructure.TmapRouteService$RouteCreateResponseImpl["features"]->java.util.ArrayList[0]->com.zetawayv.mobby.domain.route.GeoJson.FeatureDto["geometry"]->com.zetawayv.mobby.domain.route.GeoJson.GeoMetryDto["coordinates"]->java.util.ArrayList[0])
이런식으로 coordinates가 List<Double>의 형태로 올 수도, List<List<Double>>의 형태로 올 수도 있습니다.
그런데 DTO 설계시 List<Double> 이렇게 유연하지 못하게 설계를 했기 때문에 두 형태를 받지 못하는 것이었습니다.
이러면 데이터 형식을 ? 로 바꾸면 됩니다.
List<?>
이렇게 수정을 하면 제대로 받아와 지는 것을 확인할 수 있습니다.

안녕하세요! 글 잘 읽고있습니다. 혹시 Tmap api 도보 호출시 경유지넣으면 잘 나오시나요??