Spring/Spring Boot

[Spring Boot] 직렬화, 역직렬화 해주는 Object Mapper 톺아보자!

jinsang-2 2025. 4. 30. 00:03

Object Mapper (Jackson 라이브러리 사용법)

Object Mapper

  • 스프링 부트에서 직렬화, 역직렬화 수행해준다. (JACKSON 사용)
    • JSON → DTO ( 역직렬화 )
    • DTO → JSON (직렬화)
  • 변수가 아닌 method에 매칭이 된다.

Object Mapper 불러오기

@SpringBootTest
class DemoApplicationTests {
    @Autowired // 스프링에서 관리하는 빈들 중에 자동으로 생성되는 ObjectMapper를 가져오겠다.
    private ObjectMapper objectMapper;

    // dto를 json으로 바꾸는게 직렬화
    @Test
    void contextLoads() throws JsonProcessingException {
        var user = new UserRequest();
        user.setUserName("홍길동");
        user.setUserAge(10);
        user.setEmail("hong@gmail.com");
        user.setIsKorean(true);

        // dto -> json 직렬화
        var json = objectMapper.writeValueAsString(user);
        System.out.println(json); // {"user_name":"홍길동","email":"hong@gmail.com","is_korean":true,"user_age":10}

        var dto = objectMapper.readValue(json, UserRequest.class);
        System.out.println(dto); // UserRequest(userName=홍길동, UserAge=10, email=hong@gmail.com, isKorean=true)
    }
  • @Autowired : 스프링에서 관리하는 빈들 중에 타입에 맞는 객체를 자동으로 찾아서 주입해주는 기능
    • 스프링 컨테이너 안에 있는 ObjectMapper 객체를 자동으로 넣어준다.
    • ObjectMapper 는 스프링 부트가 기본적으로 자동으로 등록해주는 Bean이다.

🔨 Object Mapper 작동원리

⭐ Object Mapper는 필드를 직접 보는 것이 아니라 getter 메서드를 기준으로 JSON 직렬화를 수행한다.

  • Jackson (ObjectMapper)은 기본적으로 JSON 직렬화(JSON 문자열 만들기)는 getter 메서드만 보고, 역직렬화(JSON 문자열 → 객체 만들기)는 setter 또는 생성자를 본다.
  • getter는 get 표시된 메소드를 찾고, setter는 set 표시된 메소드를 찾음

아래와 같은 코드는 객체는 toString으로 값은 나오게 되지만, json이 빈 값으로 출력됨.

Test 코드

@SpringBootTest
class DemoApplicationTests {
    @Autowired // 스프링에서 관리하는 빈들 중에 자동으로 생성되는 ObjectMapper를 가져오겠다.
    private ObjectMapper objectMapper;

    @Test
    void contextLoads() throws JsonProcessingException {
        var user = new UserRequest("홍길동",10,"hong@gma",true);
        // dto 클래스에서 toString 실행
        System.out.println(user); // UserRequest{userName='홍길동', UserAge=10, email='hong@gma', isKorean=true}

        // dto -> json 직렬화
        var json = objectMapper.writeValueAsString(user);
        System.out.println(json); // {}
    }
}

 

dto 코드

@AllArgsConstructor
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRequest {
    private String userName;
    private Integer userAge;
    private String email;
    private Boolean isKorean ;

    @Override
    public String toString() {
        return "UserRequest{" +
                "userName='" + userName + '\\'' +
                ", UserAge=" + userAge +
                ", email='" + email + '\\'' +
                ", isKorean=" + isKorean +
                '}';
    }
}

dto 코드가 위에처럼 있으면 @AllArgsConstructor 로 매개변수들을 받아 toString으로 객체를 return 해줄 수 있지만, objectMapper.writeValueAsString(user); 로 json 형태로 직렬화 할 수 없음.

  • Jackson(ObjectMapper)은 기본적으로 getter 메서드가 있어야 필드를 직렬화함.
    • @Getter 또는 직접 작성한 getXxx() 메서드가 필요
  • toString()은 객체 문자열을 표현할 뿐, JSON 직렬화와 무관

dto 코드 개선

@AllArgsConstructor
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRequest {
    private String userName;
    private Integer userAge;
    private String email;
    private Boolean isKorean ;

    // 메소드를 찾고 get을 찾음
    public String getUserName() {
        return userName;
    }

    public Integer getUserAge() {
        return userAge;
    }

    @JsonProperty("user_email") //custom한 key 사용
    public String getEmail() {
        return email;
    }

    public Boolean getIsKorean() {
        return isKorean;
    }

    @JsonIgnore // ❗JsonIgnore로 무시하지 않으면 이 친구도 포함되서 나옴
    public String getUser(){
        return userName;
    }

    @Override
    public String toString() {
        return "UserRequest{" +
                "userName='" + userName + '\\'' +
                ", UserAge=" + userAge +
                ", email='" + email + '\\'' +
                ", isKorean=" + isKorean +
                '}';
    }
}
  • 이렇게 하면 일단 메소드를 찾음, 메소드를 찾고 get을 찾아서 getUserName이면 get과 userName를 분리하며 userName에 해당하는 내용 return
  • 직렬화 성공
    • {"user_name":"홍길동","user_age":10,"user_email":"hong@gma","is_korean":true}
    • 스네이크케이스 전략 적용(@JsonNaming)으로 userName이 user_name으로 변함
  • @JsonProperty(”EMAIL")은 수동으로 JSON 키 이름 바꿀 수 있다.
  • @JsonIgnore 해당 getter는 직렬화 대상에서 제외
    • 제외하지 않을 경우 원하지 않는 직렬화 결과가 나옴
    • {"user_name":"홍길동","user_age":10,"user_email":"hong@gma","is_korean":true, “user”:”홍길동”}
      • “user”:”홍길동” 이 추가됨

역직렬화 dto

  • @Setter를 붙여준다.
  • @Getter 사용해도 가능한 것을 알 수 있음
  • 둘 다 안할거면 @JsonProperty 를 다붙여준다.
@Setter
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRequest {
    private String userName;
    private Integer userAge;
    private String email;
    private Boolean isKorean ;

    private UserRequest(){

    }

    @Override
    public String toString() {
        return "UserRequest{" +
                "userName='" + userName + '\\'' +
                ", UserAge=" + userAge +
                ", email='" + email + '\\'' +
                ", isKorean=" + isKorean +
                '}';
    }
}
  • 둘 다 안할거면 @JsonProperty 를 다붙여준다.
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRequest {
    @JsonProperty("user_name")
    private String userName;

    @JsonProperty("user_age")
    private Integer userAge;

    @JsonProperty("user_email")
    private String email;

    @JsonProperty("is_korean")
    private Boolean isKorean ;

    @Override
    public String toString() {
        return "UserRequest{" +
                "userName='" + userName + '\\'' +
                ", UserAge=" + userAge +
                ", email='" + email + '\\'' +
                ", isKorean=" + isKorean +
                '}';
    }
}

⭐ 가장 베스트 기본 형태 사용

그냥 자동으로 해주는 어노테이션 써라~ 

@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserRequest {
    private String userName;
    private Integer userAge;
    private String email;
    private Boolean isKorean ;
}

'Spring > Spring Boot' 카테고리의 다른 글

[Spring Boot] 응답(response) 만들기!  (0) 2025.04.29
[Spring Boot] REST API 사용, DTO  (0) 2025.04.29