[Java] 자바 JSON 라이브러리 Jackson - ObjectMapper 사용법
Jackson
Jackson 라이브러리는 자바에서 데이터 처리를 위한 라이브러리로 xml, yml, properties, csv, json 등 다양한 형식의 데이터 처리가 가능한 라이브러리다. 일반적으로 자바용 JSON 라이브러리로 알려져 있다.
- Jackson 라이브러리는 스트림 방식으로 속도가 빠르고 유연하며, 어노테이션 방식으로 메타 데이터를 기술할 수 있다.
- ObjectMapper를 통해 Java 객체와 JSON 형식의 문자열 간의 직렬화(Serialization), 역직렬화(Deserialization)가 가능하다.
- 스프링 부트에서는 Jackson 라이브러리가 기본적으로 추가되어 별도의 의존성 추가 없이 사용할 수 있다.
Jackson 라이브러리 3가지 핵심 모듈
- jackson-core
- low-level streaming API를 정의하며 JSON의 구체적인 구현을 포함하고 있다.
- jackson-annotation
- Jackson 라이브러리의 표준 어노테이션을 포함하고 있다.
- jackson-databind
- 스트리밍 패키지에 대한 데이터 바인딩 지원이 구현되어 있으며, 스트리밍과 어노테이션 패키지에 의존한다.
Maven 설정
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version.core}</version>
</dependency>
ObjectMapper
ObjectMapper는 Jackson 라이브러리에서 Java 객체와 JSON 형식 간의 직렬화 및 역직렬화할 수 있도록 제공하는 기능이다.
직렬화(Serialization)
객체를 저장 가능한 상태 또는 전송 가능한 상태인 데이터 스트림 형태로 변환하는 것을 뜻한다.
Java Object → JSON
역직렬화(Deserialization)
직렬화의 반대로 데이터 스트림으로 전달받은 데이터를 객체로 변환하는 것을 뜻한다.
JSON → Java Object
ObjectMapper 사용
User 클래스
다음 코드는 name과 age 필드를 가진 User 클래스로, 예제에 사용될 생성자와 getter, toString 메서드가 구현되어 있다.
public class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\\'' +
", age=" + age +
'}';
}
}
Object ↔ Json Sring
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonTest {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
User user = new User("kim", 20);
// 직렬화(Object to Json)
String objectToJson = mapper.writeValueAsString(user);
System.out.println(objectToJson);
System.out.println();
// 역직렬화(Json to Object)
String jsonString = "{\\"name\\":\\"park\\",\\"age\\":30}";
User jsonToObject = mapper.readValue(jsonString, User.class);
System.out.println(jsonToObject);
System.out.println(jsonToObject.getName());
System.out.println(jsonToObject.getAge());
}
}
// 출력
{"name":"kim","age":20}
User{name='park', age=30}
park
30
- ObjectMapper의 writeValueAsString 메서드를 통해 객체를 Json 문자열로 변환할 수 있다.
- ObjectMapper의 readValue 메서드를 통해 지정한 Object 타입으로 변환할 수 있다.
- JSON 뿐만 아니라 List, Map 등 다양한 형식의 직렬화 및 역직렬화도 가능하다.
Jackson 라이브러리와 기본 생성자
만약, Jackson 라이브러리를 통해 역직렬화(Deserialization)를 할 때, 변환할 클래스에 기본 생성자가 없으면 다음과 같은 에러가 발생한다.
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of ...
이는 Jackson 라이브러리가 자바 리플렉션(Reflection)을 사용하기 때문이다.
자바 리플렉션은 구체적인 클래스 타입을 알지 못하더라도 해당 클래스의 타입, 변수, 메서드 등에 접근할 수 있도록 해주는 자바 API이다.
따라서 리플렉션의 동작에 의해 기본 생성자로 객체를 생성한 후 setter로 값을 주입하게 된다.
기본 생성자 없이 역직렬화하기
Jackson 라이브러리에서는 기본 생성자 없이 특정 생성자를 통해 역직렬화하도록 설정할 수 있다.
라이브러리에서 제공하는 어노테이션을 통해 설정할 수 있다.
public class User {
private String name;
private int age;
@JsonCreator
public User(@JsonProperty("name") String name,
@JsonProperty("age") int age) {
this.name = name;
this.age = age;
}
...
}
- 다음과 같이 생성자에 @JsonCreator 어노테이션을 설정하고, 파라미터에 @JsonProperty 어노테이션을 지정한다.
- 위와 같이 작성하면 Jackson 라이브러리를 사용하여 역직렬화할 때 해당 생성자를 기본으로 사용하게 된다.