Files
java-examples/docs/jackson_2.md

12 KiB

자바의 Jackson에서 XML과 JSR-310(Java Time API) 관련 기능을 다루는 글을 작성하겠습니다. Jackson은 기본적으로 JSON 처리를 위한 라이브러리지만, jackson-dataformat-xml 모듈을 통해 XML 데이터를 처리할 수 있으며, jackson-datatype-jsr310 모듈을 통해 Java 8의 JSR-310 날짜/시간 API(LocalDate, LocalDateTime 등)를 지원합니다. 이들 모듈은 JSON 처리와 유사한 방식으로 동작하지만, XML 구조나 JSR-310 데이터 타입에 특화된 어노테이션과 설정이 필요합니다.

아래에서는 XML과 JSR-310 관련 주요 어노테이션을 표로 정리한 뒤, 각 어노테이션에 대한 설명과 예시를 상세히 다루겠습니다.


Jackson XML 및 JSR-310 관련 주요 어노테이션 표

XML 관련 어노테이션 (jackson-dataformat-xml)

어노테이션 설명
@JacksonXmlRootElement XML 루트 요소의 이름과 네임스페이스를 지정
@JacksonXmlProperty XML 요소나 속성의 이름과 네임스페이스를 지정하며, 속성 여부를 설정
@JacksonXmlElementWrapper 컬렉션 필드를 감싸는 XML 요소를 지정
@JacksonXmlText 필드를 XML 요소의 텍스트 콘텐츠로 직렬화
@JacksonXmlCData 필드를 XML의 CDATA 섹션으로 직렬화

JSR-310 관련 어노테이션 (jackson-datatype-jsr310)

어노테이션 설명
@JsonFormat JSR-310 날짜/시간 객체의 직렬화 형식을 지정 (패턴, 시간대 등)
@JsonSerialize JSR-310 객체를 커스터마이즈된 직렬화 방식으로 처리
@JsonDeserialize JSR-310 객체를 커스터마이즈된 역직렬화 방식으로 처리

프로젝트 설정

XML과 JSR-310 기능을 사용하려면 pom.xml에 다음 의존성을 추가해야 합니다:

<!-- Jackson XML 지원 -->
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.17.0</version>
</dependency>
<!-- Jackson JSR-310 지원 -->
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.17.0</version>
</dependency>

각 어노테이션 상세 설명 및 예시

XML 관련 어노테이션

1. @JacksonXmlRootElement
  • 설명: XML 문서의 루트 요소 이름을 지정하며, 네임스페이스를 설정할 수 있습니다.
  • 예시:
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

@JacksonXmlRootElement(localName = "person", namespace = "http://example.com")
public class Person {
    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 {
        XmlMapper xmlMapper = new XmlMapper();
        Person person = new Person();
        person.setName("홍길동");
        String xml = xmlMapper.writeValueAsString(person);
        System.out.println(xml);
    }
}
// 출력: <person xmlns="http://example.com"><name>홍길동</name></person>
2. @JacksonXmlProperty
  • 설명: XML 요소나 속성의 이름을 지정하고, 속성으로 직렬화할지 여부를 설정합니다.
  • 예시:
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

public class Person {
    @JacksonXmlProperty(localName = "fullName")
    private String name;

    @JacksonXmlProperty(isAttribute = true)
    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 {
        XmlMapper xmlMapper = new XmlMapper();
        Person person = new Person();
        person.setName("김영희");
        person.setAge(25);
        String xml = xmlMapper.writeValueAsString(person);
        System.out.println(xml);
    }
}
// 출력: <Person age="25"><fullName>김영희</fullName></Person>
3. @JacksonXmlElementWrapper
  • 설명: 컬렉션 필드를 감싸는 XML 요소를 지정합니다.
  • 예시:
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

import java.util.Arrays;
import java.util.List;

public class Person {
    @JacksonXmlElementWrapper(localName = "hobbies")
    @JacksonXmlProperty(localName = "hobby")
    private List<String> hobbies;

    public List<String> getHobbies() { return hobbies; }
    public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        XmlMapper xmlMapper = new XmlMapper();
        Person person = new Person();
        person.setHobbies(Arrays.asList("축구", "게임"));
        String xml = xmlMapper.writeValueAsString(person);
        System.out.println(xml);
    }
}
// 출력: <Person><hobbies><hobby>축구</hobby><hobby>게임</hobby></hobbies></Person>
4. @JacksonXmlText
  • 설명: 필드를 XML 요소의 텍스트 콘텐츠로 직렬화합니다.
  • 예시:
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

public class Note {
    @JacksonXmlText
    private String content;

    public String getContent() { return content; }
    public void setContent(String content) { this.content = content; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        XmlMapper xmlMapper = new XmlMapper();
        Note note = new Note();
        note.setContent("안녕하세요");
        String xml = xmlMapper.writeValueAsString(note);
        System.out.println(xml);
    }
}
// 출력: <Note>안녕하세요</Note>
5. @JacksonXmlCData
  • 설명: 필드를 CDATA 섹션으로 감싸서 직렬화합니다. HTML 태그 등 특수 문자를 포함할 때 유용합니다.
  • 예시:
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlCData;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

public class Message {
    @JacksonXmlProperty(localName = "text")
    @JacksonXmlCData
    private String content;

    public String getContent() { return content; }
    public void setContent(String content) { this.content = content; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        XmlMapper xmlMapper = new XmlMapper();
        Message message = new Message();
        message.setContent("<b>중요</b>");
        String xml = xmlMapper.writeValueAsString(message);
        System.out.println(xml);
    }
}
// 출력: <Message><text><![CDATA[<b>중요</b>]]></text></Message>

JSR-310 관련 어노테이션

1. @JsonFormat
  • 설명: JSR-310 날짜/시간 객체의 직렬화 형식을 지정합니다. pattern 속성을 사용하여 원하는 포맷을 정의합니다.
  • 예시:
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.time.LocalDate;

public class Event {
    @JsonFormat(pattern = "yyyy/MM/dd")
    private LocalDate date;

    public LocalDate getDate() { return date; }
    public void setDate(LocalDate date) { this.date = date; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        Event event = new Event();
        event.setDate(LocalDate.of(2025, 2, 27));
        String json = mapper.writeValueAsString(event);
        System.out.println(json);
    }
}
// 출력: {"date":"2025/02/27"}
2. @JsonSerialize
  • 설명: JSR-310 객체를 사용자 정의 직렬화 방식으로 처리합니다. JavaTimeModule과 함께 커스터마이징할 때 유용합니다.
  • 예시:
import com.fasterxml.jackson.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class Event {
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate date;

    public LocalDate getDate() { return date; }
    public void setDate(LocalDate date) { this.date = date; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        Event event = new Event();
        event.setDate(LocalDate.of(2025, 2, 27));
        String json = mapper.writeValueAsString(event);
        System.out.println(json);
    }
}
// 출력: {"date":"2025-02-27"} (기본 ISO 포맷)
3. @JsonDeserialize
  • 설명: JSR-310 객체를 사용자 정의 역직렬화 방식으로 처리합니다.
  • 예시:
import com.fasterxml.jackson.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;

import java.time.LocalDate;

public class Event {
    @JsonDeserialize(using = LocalDateDeserializer.class)
    private LocalDate date;

    public LocalDate getDate() { return date; }
    public void setDate(LocalDate date) { this.date = date; }
}

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        String json = "{\"date\":\"2025-02-27\"}";
        Event event = mapper.readValue(json, Event.class);
        System.out.println(event.getDate());
    }
}
// 출력: 2025-02-27

추가 설정 및 주의사항

  1. XML 처리: XmlMapper를 사용하여 XML을 직렬화/역직렬화하며, JSON과 달리 계층적 구조를 잘 표현해야 합니다.
    XmlMapper xmlMapper = new XmlMapper();
    
  2. JSR-310 모듈 등록: JavaTimeModuleObjectMapper에 등록해야 JSR-310 타입이 기본적으로 지원됩니다.
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JavaTimeModule());
    

결론

Jackson의 XML 및 JSR-310 지원은 JSON 처리 능력을 확장하여 다양한 데이터 형식을 다룰 수 있게 해줍니다. XML 관련 어노테이션은 XML의 요소, 속성, 텍스트를 세밀히 제어하며, JSR-310 관련 어노테이션은 날짜/시간 데이터의 직렬화 형식을 사용자 정의할 수 있게 합니다. 프로젝트에서 이를 활용하려면 적절한 모듈 의존성을 추가하고, XmlMapper 또는 ObjectMapper를 올바르게 설정하는 것이 중요합니다.

추가 질문이 있다면 언제든 물어보세요!