Kotlin中的Jackson:XML重复元素的序列化与反序列化

移动开发 2026-07-08

我正在尝试把如下的XML文档序列化/反序列化到Kotlin数据类中:

<doc>
  <id>123</id>
  <items>
    <item><c>A</c><v>1</v></item>
    <item><c>B</c><v>2</v></item>
  </items>
<doc>

数据类看起来像这样:

@JacksonXmlRootElement(localName = "doc")
data class Doc(
    @JacksonXmlProperty(localName = "id")
    val id: String,

    @JacksonXmlElementWrapper (localName = "items")
    @JacksonXmlProperty(localName = "item")
    val iList: List<Item>
)

data class Item (
    @JacksonXmlProperty(localName = "c")
    val code: String,

    @JacksonXmlProperty(localName = "v")
    val value: String
)

在从POST请求反序列化时,使用默认的Jackson 3.1.2会得到如下结果(取自实际运行,因此实际的项和类名已用示例替换):

...exception [Request processing failed: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class Doc]] with root cause

tools.jackson.databind.exc.InvalidDefinitionException: Invalid definition for property 'types' (of type `Doc`): Could not find creator property with name 'types' (known Creator properties: [...(skipped)])
 at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 1]
        at tools.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:60) ~[jackson-databind-3.1.2.jar:3.1.2]

我阅读了 Jackson deserialization of list of objects with kotlinFasterXML/jackson-module-kotlin#153。看起来仍然没有好的解决方案。我尝试了最新的Jackson版本3.2.0。那个jackson-bom:3.2.0仍然包含3.1.2的部分,所以我强制包含了3.2.0:

        implementation("tools.jackson.module:jackson-module-kotlin:3.2.0")
        implementation("tools.jackson.core:jackson-core:3.2.0")
        implementation("tools.jackson.core:jackson-databind:3.2.0")
        implementation("tools.jackson.dataformat:jackson-dataformat-xml:3.2.0")
        implementation("tools.jackson.dataformat:jackson-dataformat-properties")  // 2.x should be used for jackson-3 according to the documentation

结果是能够进行反序列化。但序列化失败,显示为

... exception [Handler dispatch failed: java.lang.NoClassDefFoundError: com/fasterxml/jackson/annotation/JsonApplyView] with root cause

java.lang.ClassNotFoundException: com.fasterxml.jackson.annotation.JsonApplyView
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na]
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) ~[na:na]
        at tools.jackson.databind.introspect.JacksonAnnotationIntrospector.findApplyView(JacksonAnnotationIntrospector.java:556) ~[jackson-databind-3.2.0.jar:3.2.0]

很可能是Jackson各部分版本不匹配。那3.2.0怎么了?还没准备好吗?

进一步深入后编辑:我尝试了 Using Jackson to parse XML with repeated element 中的一个方案,因此数据类改为:

@JacksonXmlRootElement(localName = "doc")
data class Doc(
    @JacksonXmlProperty(localName = "id")
    val id: String,

    @JacksonXmlElementWrapper (localName = "items")
    @JacksonXmlProperty(localName = "items")
    val iList: List<Item>
) {

  @JacksonXmlRootElement(localName = "item")
  data class Item (
      @JacksonXmlProperty(localName = "c")
      val code: String,

      @JacksonXmlProperty(localName = "v")
      val value: String
  )
}

是的,反序列化工作,但使用3.1.2进行序列化时结果很糟糕

<doc>
  <id>123</id>
  <items>
    <items><item><c>A</c><v>1</v></item></items>
    <items><item><c>B</c><v>2</v></item></items>
  </items>
<doc>

解决方案

嗯,看起来Jackson对于处理XML来说不是一个好选择(至少对我而言是这样),那就转向kotlinx.serialization和 xmlutil

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章