자바의 Jackson에 대해 설명하는 글을 작성하겠습니다. Jackson은 자바에서 JSON 데이터를 처리하기 위해 널리 사용되는 라이브러리로, 객체와 JSON 간의 직렬화(Serialization) 및 역직렬화(Deserialization)를 쉽게 수행할 수 있게 해줍니다. 특히, Jackson의 어노테이션은 이러한 변환 과정을 세밀하게 제어할 수 있도록 도와줍니다. 아래에서는 Jackson의 주요 어노테이션을 표로 정리한 뒤, 각 어노테이션에 대한 상세 설명과 예시를 제공하겠습니다. --- ### Jackson 주요 어노테이션 표 | 어노테이션 | 설명 | |----------------------------|------------------------------------------------------------------------------------------| | `@JsonProperty` | JSON 키와 자바 필드/메서드 이름을 매핑하거나, 직렬화/역직렬화 시 속성 이름을 지정 | | `@JsonIgnore` | 직렬화 및 역직렬화 시 특정 필드를 무시 | | `@JsonIgnoreProperties` | 클래스 레벨에서 직렬화/역직렬화 시 무시할 속성(들)을 지정 | | `@JsonInclude` | 직렬화 시 특정 조건(예: null 값 제외)에 따라 필드를 포함하거나 제외 | | `@JsonCreator` | 역직렬화 시 사용할 생성자나 팩토리 메서드를 지정 | | `@JsonSetter` | 역직렬화 시 특정 Setter 메서드를 JSON 속성과 매핑 | | `@JsonGetter` | 직렬화 시 특정 Getter 메서드를 JSON 속성으로 사용 | | `@JsonAnySetter` | 정의되지 않은 JSON 속성을 Map 형태로 처리 | | `@JsonAnyGetter` | Map의 내용을 추가적인 JSON 속성으로 직렬화 | | `@JsonManagedReference` | 객체 간 순환 참조에서 부모 객체를 직렬화 | | `@JsonBackReference` | 객체 간 순환 참조에서 자식 객체를 직렬화에서 제외 | | `@JsonIdentityInfo` | 순환 참조 문제를 해결하기 위해 객체의 고유 식별자를 사용 | | `@JsonTypeInfo` | 다형성 타입 정보를 JSON에 포함시켜 직렬화/역직렬화 시 올바른 타입으로 처리 | | `@JsonSubTypes` | `@JsonTypeInfo`와 함께 사용되며, 하위 타입을 명시 | | `@JsonView` | 특정 뷰(View)에 따라 직렬화/역직렬화 대상을 제한 | | `@JacksonInject` | JSON 데이터 대신 외부에서 주입된 값을 필드에 설정 | --- ### 각 어노테이션 상세 설명 및 예시 #### 1. `@JsonProperty` - **설명**: JSON 속성 이름과 자바 필드/메서드 이름을 매핑하거나, 이름을 강제로 지정합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JsonProperty; public class Person { @JsonProperty("fullName") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); Person person = new Person(); person.setName("홍길동"); String json = mapper.writeValueAsString(person); System.out.println(json); // {"fullName":"홍길동"} } } ``` #### 2. `@JsonIgnore` - **설명**: 직렬화 및 역직렬화 시 특정 필드를 제외합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JsonIgnore; public class Person { private String name; @JsonIgnore private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); Person person = new Person(); person.setName("김영희"); person.setAge(25); String json = mapper.writeValueAsString(person); System.out.println(json); // {"name":"김영희"} } } ``` #### 3. `@JsonIgnoreProperties` - **설명**: 클래스 레벨에서 무시할 속성을 지정하거나, 알 수 없는 속성을 무시하도록 설정합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties({"age", "ignoreUnknown = true"}) public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); String json = "{\"name\":\"이철수\",\"age\":30,\"extra\":\"data\"}"; Person person = mapper.readValue(json, Person.class); System.out.println(person.getName()); // "이철수" } } ``` #### 4. `@JsonInclude` - **설명**: 직렬화 시 null 값이나 빈 값 등을 제외하는 조건을 설정합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JsonInclude; @JsonInclude(JsonInclude.Include.NON_NULL) public class Person { private String name; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); Person person = new Person(); person.setName("박민수"); String json = mapper.writeValueAsString(person); System.out.println(json); // {"name":"박민수"} } } ``` #### 5. `@JsonCreator` - **설명**: 역직렬화 시 사용할 생성자나 팩토리 메서드를 지정합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class Person { private final String name; @JsonCreator public Person(@JsonProperty("name") String name) { this.name = name; } public String getName() { return name; } } public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); String json = "{\"name\":\"최수진\"}"; Person person = mapper.readValue(json, Person.class); System.out.println(person.getName()); // "최수진" } } ``` #### 6. `@JsonSetter` - **설명**: 역직렬화 시 Setter 메서드를 특정 JSON 속성과 매핑합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JsonSetter; public class Person { private String name; @JsonSetter("fullName") public void setName(String name) { this.name = name; } public String getName() { return name; } } public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); String json = "{\"fullName\":\"김지영\"}"; Person person = mapper.readValue(json, Person.class); System.out.println(person.getName()); // "김지영" } } ``` #### 7. `@JsonGetter` - **설명**: 직렬화 시 Getter 메서드를 JSON 속성으로 사용합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JsonGetter; public class Person { private String name; @JsonGetter("fullName") public String getName() { return name; } public void setName(String name) { this.name = name; } } public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); Person person = new Person(); person.setName("윤서진"); String json = mapper.writeValueAsString(person); System.out.println(json); // {"fullName":"윤서진"} } } ``` #### 8. `@JsonAnySetter` - **설명**: 정의되지 않은 JSON 속성을 Map으로 처리합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JsonAnySetter; import java.util.HashMap; import java.util.Map; public class Person { private Map properties = new HashMap<>(); @JsonAnySetter public void setProperty(String key, Object value) { properties.put(key, value); } public Map getProperties() { return properties; } } public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); String json = "{\"name\":\"이정훈\",\"age\":29}"; Person person = mapper.readValue(json, Person.class); System.out.println(person.getProperties()); // {name=이정훈, age=29} } } ``` #### 9. `@JsonAnyGetter` - **설명**: Map의 내용을 추가적인 JSON 속성으로 직렬화합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JsonAnyGetter; import java.util.HashMap; import java.util.Map; public class Person { private Map properties = new HashMap<>(); @JsonAnyGetter public Map getProperties() { return properties; } public void setProperty(String key, Object value) { properties.put(key, value); } } public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); Person person = new Person(); person.setProperty("name", "최영미"); person.setProperty("age", 35); String json = mapper.writeValueAsString(person); System.out.println(json); // {"name":"최영미","age":35} } } ``` #### 10. `@JsonManagedReference`와 `@JsonBackReference` - **설명**: 순환 참조 문제를 해결하기 위해 부모-자식 관계를 정의합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonBackReference; public class Parent { @JsonManagedReference public Child child; public void setChild(Child child) { this.child = child; } } public class Child { @JsonBackReference public Parent parent; public void setParent(Parent parent) { this.parent = parent; } } public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); Parent parent = new Parent(); Child child = new Child(); parent.setChild(child); child.setParent(parent); String json = mapper.writeValueAsString(parent); System.out.println(json); // {"child":{}} } } ``` #### 11. `@JsonIdentityInfo` - **설명**: 순환 참조를 객체 ID로 해결합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.ObjectIdGenerators; @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class Person { private int id; private String name; private Person friend; public Person(int id, String name) { this.id = id; this.name = name; } public void setFriend(Person friend) { this.friend = friend; } public String getName() { return name; } } public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); Person p1 = new Person(1, "김태양"); Person p2 = new Person(2, "이수진"); p1.setFriend(p2); p2.setFriend(p1); String json = mapper.writeValueAsString(p1); System.out.println(json); // {"id":1,"name":"김태양","friend":{"id":2,"name":"이수진","friend":1}} } } ``` #### 12. `@JsonTypeInfo`와 `@JsonSubTypes` - **설명**: 다형성을 처리하기 위해 타입 정보를 JSON에 포함합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @JsonSubTypes({ @Type(value = Dog.class, name = "dog"), @Type(value = Cat.class, name = "cat") }) public abstract class Animal { public String name; } public class Dog extends Animal {} public class Cat extends Animal {} public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); Dog dog = new Dog(); dog.name = "멍멍이"; String json = mapper.writeValueAsString(dog); System.out.println(json); // {"type":"dog","name":"멍멍이"} } } ``` #### 13. `@JsonView` - **설명**: 특정 뷰에 따라 직렬화 대상을 제한합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JsonView; public class Person { public interface PublicView {} public interface PrivateView extends PublicView {} @JsonView(PublicView.class) private String name; @JsonView(PrivateView.class) private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); Person person = new Person("박준영", 27); String json = mapper.writerWithView(Person.PublicView.class).writeValueAsString(person); System.out.println(json); // {"name":"박준영"} } } ``` #### 14. `@JacksonInject` - **설명**: JSON 데이터가 아닌 외부에서 주입된 값을 사용합니다. - **예시**: ```java import com.fasterxml.jackson.annotation.JacksonInject; public class Person { @JacksonInject private String source; private String name; public Person(String name) { this.name = name; } public String getSource() { return source; } public String getName() { return name; } } public class Main { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); InjectableValues inject = new InjectableValues.Std().addValue(String.class, "외부 소스"); Person person = mapper.reader(inject).forType(Person.class) .readValue("{\"name\":\"최민수\"}"); System.out.println(person.getSource()); // "외부 소스" } } ``` --- ### 결론 Jackson은 강력한 JSON 처리 기능을 제공하며, 위의 어노테이션들은 이를 세밀하게 제어할 수 있게 해줍니다. 다형성 처리, 순환 참조 해결, 속성 이름 매핑 등 다양한 기능을 통해 개발자는 유연하고 효율적인 JSON 처리를 구현할 수 있습니다. 프로젝트에서 Jackson을 사용할 때는 팀원 모두가 관련 어노테이션을 이해하고, 적절한 설정(예: 의존성 추가, IDE 플러그인 설치)을 통해 효율적으로 활용하는 것이 중요합니다. 궁금한 점이 있다면 언제든 물어보세요!