Java Object <=> XML 변환을 위해 jackson-dataformat-xml 라이브러리를 사용했었는데 생각치도 못한 버그를 보게 되었다.
(2025년 06월) 현재 시점에는 Jackson 라이브러리를 직접 수정하지 않는이상 따로 해결방법은 없어 보이며 XML 변환 라이브러리로 Jackson 을 추천하지 않으며 JAXB를 추천한다.
다행히 JAXB 라이브러리가 Jackson-dataformat-xml 과 사용방법에 크게 차이가 나지 않아서 JAXB 로 변환작업을 하는데 생각만큼 공수가 많이 들지는 않았다.
결과와 소스는 아래와 같다.
- List 항목에 다형성을 위한 인터페이스 사용 시 Wrapper 에 지정한 엘리먼트가 한번씩 더 표시가 된다.
- JSON 에서는 예상한대로 결과가 나오지만 XML 에서만 문제가 발생한다.
[ 소스와 결과 ]
======== 결과 =========
{
"parameterDefinitions" : [ {
"hudson.model.BooleanParameterDefinition" : {
"name" : "test1",
"description" : null,
"defaultValue" : true
}
}, {
"hudson.model.StringParameterDefinition" : {
"name" : "test2",
"description" : null,
"defaultValue" : true
}
} ]
}
<RootElement>
<parameterDefinitions>
<parameterDefinitions>
<hudson.model.BooleanParameterDefinition>
<name>test1</name>
<description/>
<defaultValue>true</defaultValue>
</hudson.model.BooleanParameterDefinition>
</parameterDefinitions>
<parameterDefinitions>
<hudson.model.StringParameterDefinition>
<name>test2</name>
<description/>
<defaultValue>true</defaultValue>
</hudson.model.StringParameterDefinition>
</parameterDefinitions>
</parameterDefinitions>
</RootElement>
======== 소스 =========
RootElement job = new RootElement();
job.setParameterDefinitions(List.of(
BooleanParameterDefinition.builder()
.name("test1")
.defaultValue(true)
.build(),
StringParameterDefinition.builder()
.name("test2")
.defaultValue(true)
.build()
));
ObjectMapper objMapper = new ObjectMapper();
objMapper.enable(SerializationFeature.INDENT_OUTPUT);
System.out.println(objMapper.writeValueAsString(job));
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
System.out.println(xmlMapper.writeValueAsString(job));
========================
// 인터페이스 List 를 Wrapper 로 감싸고 있는경우
@JacksonXmlElementWrapper(localName = "parameterDefinitions")
private List<ParameterDefinition> parameterDefinitions;
// 인터페이스 내용 (JsonSubTypes 를 사용)
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME, // XML 태그 이름을 타입 식별자로 사용
include = JsonTypeInfo.As.WRAPPER_OBJECT // 각 타입이 자신의 태그 이름으로 감싸짐
)
@JsonSubTypes({
@JsonSubTypes.Type(value = BooleanParameterDefinition.class, name = "hudson.model.BooleanParameterDefinition"),
@JsonSubTypes.Type(value = StringParameterDefinition.class, name = "hudson.model.StringParameterDefinition")
})
public interface ParameterDefinition {
String getName(); // 모든 파라미터 정의는 이름을 가짐
String getDescription(); // 모든 파라미터 정의는 설명을 가질 수 있음
}
1004lucifer
[ 전체 소스 ]
GitHub Source : https://github.com/1004lucifer/Test_Java/tree/main/Library/Jackson/Bug-JacksonXmlElementWrapper
Jackson 커미터분께서 XML 모듈에 대한 기능은 제한적인것 같은 이야기를 했던 글이 있다.
- https://github.com/FasterXML/jackson-dataformat-xml/issues/266#issuecomment-335511725
참고
- https://github.com/FasterXML/jackson-dataformat-xml/issues/514
- https://github.com/FasterXML/jackson-dataformat-xml/issues/299
- https://koiking.tistory.com/38
댓글
댓글 쓰기