반응형
자바의 ObjectMapper를 알아보자.
1. ObjectMapper란 무엇인가?
ObjectMapper는 Jackson 라이브러리에서 제공하는 클래스 중 하나로, Java 객체를 JSON으로, 또는 JSON을 Java 객체로 변환하는 데 사용된다. 이러한 변환 과정을 직렬화(Serialization)와 역직렬화(Deserialization)라고 한다.
JSON 직렬화란?
- 직렬화는 객체의 상태를 바이트 스트림이나 문자열과 같은 표준 형식으로 변환하는 과정이다. JSON 직렬화는 특히 웹 애플리케이션이나 API 통신에서 데이터 교환의 표준 형식으로 널리 사용된다. JSON은 가볍고, 인간이 읽기 쉬우며, 대부분의 프로그래밍 언어에서 쉽게 파싱할 수 있다는 장점이 있다.
왜 JSON을 선택할까?
- JSON은 간결한 구조와 높은 호환성 덕분에 다양한 시스템 간 데이터 교환에 적합하다. XML과 비교했을 때, 더 적은 메타데이터를 사용하여 데이터 전송이 효율적이며, 자바스크립트와의 자연스러운 통합으로 웹 개발에서 특히 선호된다.
2. ObjectMapper를 활용한 JSON 직렬화
기본 사용법
- 아래 예제에서 writeValueAsString 메서드는 객체를 JSON 문자열로 변환하고, writeValueAsBytes 메서드는 객체를 JSON 바이트 배열로 변환한다.
import com.fasterxml.jackson.databind.ObjectMapper;
public class ObjectMapperExample {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
User user = new User("john_doe", "john@example.com");
// 객체를 JSON 문자열로 변환
String jsonString = objectMapper.writeValueAsString(user);
System.out.println(jsonString);
// 객체를 JSON 바이트 배열로 변환
byte[] jsonBytes = objectMapper.writeValueAsBytes(user);
System.out.println(Arrays.toString(jsonBytes));
}
}
class User {
private String username;
private String email;
// 생성자, getters, setters 생략
}
JSON 문자열과 바이트 배열의 차이
- JSON 문자열 (writeValueAsString)
- 주로 HTTP 응답, 로깅, 데이터 교환 등에서 사용된다.
- 사람이 읽기 쉬워 디버깅에 유리하다.
- JSON 바이트 배열 (writeValueAsBytes)
- 이진 데이터 전송, 파일 저장, 메모리 효율성이 중요한 경우에 사용된다.
- 네트워크 프로토콜이나 특정 저장 방식에서 유용하다.
예제 코드1. JSON 문자열 변환
import com.fasterxml.jackson.databind.ObjectMapper;
public class WriteValueAsStringExample {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
Person person = new Person("스타크", 27);
// 객체를 문자열로 변환
String personString = objectMapper.writeValueAsString(person);
System.out.println(personString);
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getters, setters 생략
}
결과
{"name":"스타크","age":27}
예제 코드2. JSON 바이트 배열 변환
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Arrays;
public class WriteValueAsBytesExample {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
Person person = new Person("스타크", 27);
// 객체를 바이트 배열로 변환
byte[] personBytes = objectMapper.writeValueAsBytes(person);
// 바이트 배열을 출력
System.out.println(Arrays.toString(personBytes));
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getters, setters 생략
}
결과
[123, 34, 110, 97, 109, 101, 34, 58, 34, 스타크, 34, 44, 34, 97, 103, 101, 34, 58, 50, 55, 125]
3. ObjectMapper의 고급 설정과 주의 사항
ObjectMapper는 기본적인 변환 외에도 다양한 설정을 통해 변환 과정을 세밀하게 조절할 수 있다.
또한, 직렬화 과정에서 발생할 수 있는 문제점들도 있다.
고급 설정1. JSON 포맷팅
- 기본적으로 ObjectMapper는 최소한의 공백을 사용하여 JSON을 출력한다. writerWithDefaultPrettyPrinter 메서드를 사용하면 가독성이 높은 형식으로 JSON을 출력할 수도 있다.
String prettyJson = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user);
System.out.println(prettyJson);
결과
{
"username" : "john_doe",
"email" : "john@example.com"
}
고급 설정2. 날짜 형식 설정
- Java의 Date 객체는 기본적으로 타임스탬프로 직렬화된다.
- 원하는 형식으로 날짜를 출력하려면 setDateFormat 메서드를 사용한다.
import java.text.SimpleDateFormat;
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
String jsonWithDate = objectMapper.writeValueAsString(new Event(new Date()));
System.out.println(jsonWithDate);
직렬화 시 주의 사항1. 순환 참조
- 객체 간에 순환 참조가 있을 경우, 직렬화 과정에서 무한 루프가 발생할 수 있다. 이를 방지하기 위해 @JsonManagedReference와 @JsonBackReference 애노테이션을 사용할 수 있다.
public class User {
public String name;
@JsonManagedReference
public List<Item> items;
}
public class Item {
public String itemName;
@JsonBackReference
public User user;
}
직렬화 시 주의 사항2. 무한 재귀 방지
- 특정 객체의 getter 메서드가 다시 원래 객체를 반환하는 경우, 무한 재귀가 발생할 수 있다. 이럴 때는 @JsonIgnore 애노테이션을 사용하여 특정 필드의 직렬화를 방지할 수 있다.
public class User {
public String name;
@JsonIgnore
public User friend;
}
4. 바이트 배열과 문자열: 언제 어떤 메서드를 사용할까?
ObjectMapper는 writeValueAsBytes와 writeValueAsString 두 가지 주요 메서드를 통해 객체를 JSON으로 변환한다.
각각의 반환 형식과 사용 사례를 이해하고 적절히 선택하는 것이 중요하다.
1. writeValueAsBytes
- 반환 형식: 바이트 배열
- 사용 사례:
- 이진 프로토콜을 사용하는 네트워크 통신
- 파일 시스템에 직접 저장 (특히 이진 파일 형식)
- 메모리 효율성이 중요한 대용량 데이터 처리
예제 코드
byte[] jsonBytes = objectMapper.writeValueAsBytes(user);
2. writeValueAsString
- 반환 형식: 문자열
- 사용 사례:
- HTTP 응답 전송
- 로깅 시스템에 JSON 형식의 로그 기록
- 다른 시스템과의 데이터 교환
예제 코드
String jsonString = objectMapper.writeValueAsString(user);
System.out.println(jsonString);
차이점 요약
- 반환 형식: writeValueAsBytes는 바이트 배열, writeValueAsString는 문자열을 반환한다.
- 사용 상황: 이진 데이터 처리나 파일 저장 시에는 writeValueAsBytes를, HTTP 응답이나 로깅 등 일반적인 데이터 교환에는 writeValueAsString을 사용하는 것이 적합하다.
반응형
'JAVA' 카테고리의 다른 글
[Java] 동시성과 병렬 처리 part2: 함정, 고급 패턴, 성능 최적화 (1) | 2023.11.01 |
---|---|
[Java] 동시성과 병렬 처리 part1 (1) | 2023.10.31 |
[Java] Stream: mapToInt 함수로 점수 합산하기 (0) | 2023.09.27 |
[Java] 예제로 이해하는 자바 스트림(stream) (0) | 2023.09.27 |
[Java] 익명 클래스 (Anonymous Class)란? (0) | 2023.08.09 |