ObjectMapper에 대해 알아보자.

지니·2024년 3월 23일
0

Spring Boot를 이용해 개발을 하면서 ObjectMapper를 직간접적으로 사용하고 있었다. 기본 ObjectMapper를 사용했을 때 자주 잊어버리는 항목인 것 같아 이번 기회에 정리해보았다.


이제부터 아래 클래스를 가지고 놀 예정이다.
class TestObject {
    private Long id;
    private String name;
}

1. 역직렬화 (String -> Object)

Object에 해당하는 클래스에 @NoArgsConstructor가 필요하고 @Getter 또는 @Setter가 필요하다.

spring boot에서 request json 문자열을 DTO 객체로 변환하는 과정이다.


예시

예시 코드

ObjectMapper mapper = new ObjectMapper();
final String value = "{\"name\":\"test\",\"id\":1}";

TestObject resObject = mapper.readValue(value, TestObject.class);

1) TestObject에 @Getter 또는 @Setter를 붙이지 않은 경우

Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "name" (class com.test.teamlog.global.security.TestObject), not marked as ignorable (0 known properties: ])
 at [Source: (String)"{"name":"test","id":1}"; line: 1, column: 10] (through reference chain: com.test.teamlog.global.security.TestObject["name"])

필드가 없다면서 UnrecognizedPropertyException이 발생한다.


2) TestObject에 @NoArgsConstructor를 붙이지 않은 경우

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.test.teamlog.global.security.TestObject` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

no Creators, like default constructor 라면서 기본 생성자를 만들어달라고 에러를 뱉는다.



추가 내용

인턴 시절 실무에서 뭣모르고 했다가 종종 버그가 발생했던 사례가 떠올라 적어보기로 했다. 당시 특정 필드의 값을 request로부터 받는 시점에 변환하고 싶었던 모양이었는지 request dto에 해당하는 클래스의 필드에 대한 setter를 재정의했다. (왜 그랬지...) 아래와 같이 말이다.

@Getter
class TestObject {
    private Long id;
    private String name;

    public void setName(String name) {
        this.name = "Hello, my name is " + name;
    }
}

이렇게 되면 request에서 {"id":1,"name":"name"} 와 같이 보내면 name은 Hello, my name is test가 된다. ObjectMapper를 통해 역직렬화할 때 setter의 우선순위가 더 높은 것 같다. 히스토리를 모르는 다른 개발자를 당황시키기 딱 좋은 코드다. 기본 Setter, Getter는 건드리지 말자.




2. 직렬화 (Object -> String)

spring boot에서 DTO 객체 -> response로 변환하는 과정이다.

1) @Getter가 없는 경우

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.test.teamlog.global.security.TestObject and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

기본적으로 public인 필드에 접근하게 된다. 즉, 필드를 public으로 열어주거나 getter 메소드를 열어주어 접근 가능하도록 해야한다.





profile
Coding Duck

0개의 댓글