본문 바로가기

Back-end/SpringBoot

[SpringBoot] Object Mapper

✅Object Mapper

Java Object와 JSON의 형태를 자유롭게 변경하기 위해 사용되는 것이 Object Mapper이다.

  1. Serialize: Java Object → JSON
  2. Deserialize: JSON → Java Object

형태를 바꿔주는 기능은 위의 두 가지 방식으로 나누어져 있으며 Object Mapper의 가장 중요한 기능이다

 

dependencies {
  ...
  implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.0'
}

 

이렇게  Gradle에 의존성을 추가해도되지만

 

implementation 'org.springframework.boot:spring-boot-starter-web'

 

해당 의존성에 자동으로 포함되어있어서 따로 추가적으로 의존성을 추가안해도된다.

 

처음에 이것을 쓰게된 계기는 Naver OpenApi에서 책 검색기능을 구현하는데 Json 으로 데이터가 왔다.

Json으로 온데이터를 Java쪽에서 추가적으로 로직을 수행하기 위해서 이다.

 

🔎 예제

public class Member {

  private int id;
  private String name;

  public Member(int id, String name) {
    this.id = id;
    this.name = name;
  }

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

}

 

위와 같은 Java class가 있다고 가정하자. 이 Member class를 이용하여 어떻게 serialization, deserialization이 가능한 것인지 알아볼 것이다.

 

✅ Serialization (Java Object → JSON) 

JSON의 형태로 serialize 시킬 때 objectMapper의 writeValue()  writeValueAsString() 메소드를 사용한다. 이 두 메소드는 각각 파일로 변환, 문자열로 변환의 기능을 갖고 있다

 

public class ObjectMapperPractice {
  public static void main(String[] args) {
    ObjectMapper objectMapper = new ObjectMapper();
    Member member = new Member(1, "Sangyup");

    // Java Object -> JSON
    // 파일 출력: member.json
    try {
      objectMapper.writeValue(new File("원하는 경로/member.json"), member);
    } catch (IOException e) {
      e.printStackTrace();
    }
    
    // 문자열 출력
    try {
      String memberAsJsonString = objectMapper.writeValueAsString(member);
      System.out.println(memberAsJsonString);
    } catch (JsonProcessingException e) {
      e.printStackTrace();
    }
    // 출력값: {"id":1,"name":"Sangyup"}
  }
}

 

이 때, serialize 하려고 하는 class에 Getter가 없다면 안된다.

 

Jackson 라이브러리는 serialize할 때, Getter의 prefix를 제거하고 소문자로 만들어서 식별하기 때문에 가져올 Getter가 없다면 오류를 내보내게 된다.

 

 

✅ Deserialization (JSON → Java Object) 

SON을 Java Object로 deserialize시킬 때는 objectMapper의 readValue() 메소드를 이용한다

public class ObjectMapperPractice {
  public static void main(String[] args) {
    ObjectMapper objectMapper = new ObjectMapper();

    // JSON -> Java Object
    String json = "{\"id\":2, \"name\":\"Sangyup Lee\"}";
    try {
      Member newMember = objectMapper.readValue(json, Member.class);
      System.out.println(newMember);
      System.out.println(newMember.getId() + " " + newMember.getName());
    } catch (JsonProcessingException e) {
      e.printStackTrace();
    }
  }
}

 

역직렬화를 진행시 해당 클래스에는 기본생성자가 있어야지 Java Object가 생성된다.

 

 

🖥️ Naver OpenAPI  역직렬화

 

@Override
public List<BookDto> searchBooks(String query, Integer display) {
    String encodedQuery = URLEncoder.encode(query, StandardCharsets.UTF_8);
    String apiURL = NAVER_BOOK_API_URL + "?query=" + encodedQuery + "&display=" + display;
    Map<String, String> requestHeaders = new HashMap<>();
    requestHeaders.put("X-Naver-Client-Id", clientId);
    requestHeaders.put("X-Naver-Client-Secret", clientSecret);
    String responseBody = get(apiURL,requestHeaders);

    List<BookDto> books = new ArrayList<>();
    try {
        ObjectMapper mapper = new ObjectMapper();
        NaverBookResponse bookResponse = mapper.readValue(responseBody, NaverBookResponse.class);

        if (bookResponse != null && bookResponse.getItems() != null && !bookResponse.getItems().isEmpty()) {
            books = bookResponse.getItems().stream().map(this::convertToBookDto)
                    .collect(Collectors.toList());
            logger.info("검색 결과: {} 건", books.size());
        } else {
            logger.info("검색 결과 없음: {}", query);
        }
    } catch (JsonProcessingException e) {
        throw new RuntimeException(e);
    }
    return books;
}

 

@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
public class NaverBookResponse {
    private List<NaverBookItem> items;  // Book Item
    private Integer total;              // 전체 카운트
}
@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
public class NaverBookItem {
    private String title;       // 제목
    private String author;      // 작가
    private String publisher;   // 출판사
    private String pubdate;     // 출판날짜
    private String description; // 설명
    private String isbn;        // ISBN
    private String image;       // 이미지 URL
    private String link;        // 상세 정보 URL
    private String discount;    // 재고
}

 

✏️ 공부한점

API에서 받아온 Json 데이터를 Java Object로 만들기위해서 mapper.readValue를  사용했다.

 

readValue( "지적된 타입으로 변환할 대상", "대상을 어떤 타입으로 변환할 것인지 클래스명시 ")