ObjectMapper 사용법

최준호·2022년 11월 3일
0

업무

목록 보기
22/31
post-thumbnail

👏 ObjectMapper

spring에서 json 데이터를 파싱하거나 object를 json 형태의 string으로 변환할 때 자주 사용되는 라이브러리이다. spring 자체에서 제공하기 때문에 gson이라던지 simpleJson 같은 라이브러리를 따로 추가하지 않아도 사용할 수 있다.

😂 업무중 발생한 문제!

다른 회사 api와 연동하여 데이터를 주고 받을 일이 있었다. 그런데 전혀 생각하지 못했던 문제가 발생했다.

그것은 요청하는 데이터와 받는 데이터 모두 영어 대문자인것이다. 솔직히 그냥 Map으로 데이터 담아서 보내고 반환되는 데이터를 Map으로 받으면 key값에 그대로 전달되고 반환되기 때문에 크게 문제가 되지 않을 수 있다. 하지만 뭔가 Map에 데이터를 담는 행위가 나는 싫었고 반환 받는 데이터를 Map으로 받기가 싫었다. 그래서 문제를 해결해보려고 한다!

📗 문제 해결

📄 ObjectMapper는 Thread Safe할까?

결론부터 말하면 java api 공식 문서에 따르면 Mapper instance는

Mapper instances are fully thread-safe provided that ALL configuration of the instance occurs before ANY read or write calls

해당 구문을 보면 매퍼 인스턴스는 읽기와 쓰기 이전에 모든 설정에 있어 완전히 thread-safe 하다고 설명되어 있다.

git hub objectmapper 재사용에 관련한 이슈를 보면 Jackson의 ObjectMapper를 생성하는 것은 새로운 인스턴스를 생성하는 것은 비용이 많이 들기 때문에 성능을 저하시키는 요인이 된다고 설명되어 있다.

📄 요청 데이터부터 문제를 해결!

요청하는 데이터를 String으로 만들 때 발생하는 문제는

다음과 같이 모두 대문자로 보내야하는 데이터가 objectMapper를 통하면 카멜 규칙에 따라 소문자로 취환되는 문제가 발생했다.

그래서 해당 데이터로 요청을 보내면 데이터를 받는 쪽에서 파싱에서 에러가 발생하여 전송이 안되는 문제가 생겼다. 이 문제를 해결하는 방법은 기존의 롬복으로 getter를 만들었던 부분을 직접 생성하여 작성하면 되는데

com.fasterxml.jackson.annotation.JsonProperty@JsonProperty 어노테이션을 사용해주면 된다.

@Builder
@AllArgsConstructor
public class Request {

    @NonNull
    private String SITE_NAME;

    @JsonProperty("SITE_NAME")
    public String getSITE_NAME() {
        return SITE_NAME;
    }
}

다음과 같이 작성해주면

위에서 소문자로 치환되던 문제가 해결되었다!

📄 반환 데이터 문제 해결!

이제 다음 문제는 요청을 한 뒤에 반환되는 데이터가 모두 대문자인 것을 파싱하는 부분이다.

데이터가 반환이 되었지만 반환된 데이터의 키값들이 모두 대문자였기 때문에 mapper가 제대로 매칭을 해주지 못하는 문제로 인해 모두 null로 반환되어버리는 문제가 발생했다.

해당 문제는

objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);

설정을 통해 해결할 수 있지만 해당 방법으로 사용하게되면 해당 메서드는 deprecated 되었다고 뜨면서 새로운 메서드를 사용할 것을 권장한다.

또한 objectMapper를 빈으로 등록해서 사용하는 입장에서 설정이 바뀌는 것이 어떻게 동작할지 몰라 달갑지 않았다.

그래서 내가 선택한 방법은 위에서는 새로운 mapper를 생성하는 것이 별로라고 했지만 이렇게 특별한 설정이 필요한 경우에는 사용해야될 것 같았기 때문에 새로운 메서드에 맞게 작성해보았다.

JsonMapper jsonMapper = JsonMapper.builder().configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true).build();

...
// api 대상 회사와 통신 후 반환 받은 값을 resultString에 저장

ResultDto response = jsonMapper.readValue(resultString, ResultDto.class);

이전에 사용하던 ObjectMapper 대신 JsonMapper를 사용하면 되는데 다음과 같이 JsonMapper를 생성하여 반환 받아 ObjectMapper와 동일하게 사용하면 된다.

JsonMapper는 2.10 버전 이후부터 추가된 class로

ObjectMapper를 상속받아서 기능을 추가(?) 했다기 보다는 최근 코드 스타일로 생성할 수 있도록 도와주는 메서드들을 주로 정의해주는거 같다.

사진과 같이 ObjectMapper를 상속받았기에 기존에 기능을 그대로 사용할 수 있어 그대로 사용해주면 된다.

그럼 이제 대문자인 반환 값에서도 데이터를 잘 가져와 객체에 넣어주는 것을 확인할 수 있다!

profile
해당 주소로 이전하였습니다. 감사합니다. https://ililil9482.tistory.com

0개의 댓글