[Jackson-XML][Bug] List 항목에 Interface 사용 시 Wrapper 요소 중복 출력 버그 (XML 에서만 발생)

 

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


댓글