You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jackson替代SimpleXML @ElementListUnion的方案及自定义序列化实现

Jackson替代SimpleXML @ElementListUnion的方案与实现

Jackson没有提供和SimpleXML的@ElementListUnion完全等价的注解,但有两种可行的实现方式:

一、使用Jackson类型注解实现(简洁方案)

通过@JsonTypeInfo和@JsonSubTypes结合XML配置,可以直接生成按类型命名的标签,无需自定义序列化器。

代码示例

  1. 定义Root类:
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import java.util.List;

class Root {
    // 禁用列表外层包装标签
    @JacksonXmlElementWrapper(useWrapping = false)
    // 指定用包装对象的方式体现类型,标签名对应子类型的name属性
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
    // 映射类型与标签名
    @JsonSubTypes({
        @JsonSubTypes.Type(value = Foo.class, name = "Foo"),
        @JsonSubTypes.Type(value = Bar.class, name = "Bar")
    })
    protected List<Object> fooOrBar;

    // 构造方法、Getter/Setter 省略
}
  1. 序列化后生成的XML结构:
<Root>
  <Foo>
    {correct Foo serialization}
  </Foo>
  <Bar>
    {correct Bar serialization}
  </Bar>
</Root>

这种方式适合类型固定的场景,配置简单,无需额外编写序列化逻辑。

二、自定义序列化器实现(灵活方案)

如果需要更灵活的标签名映射规则(比如动态生成标签名),可以编写自定义List序列化器,根据元素类型动态修改标签名。

代码示例

  1. 定义Root类,指定自定义序列化器:
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.util.List;

class Root {
    @JsonSerialize(using = PolymorphicListXmlSerializer.class)
    protected List<Object> fooOrBar;

    // 构造方法、Getter/Setter 省略
}
  1. 实现自定义序列化器:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;

import java.io.IOException;

public class PolymorphicListXmlSerializer extends StdSerializer<List<?>> {

    protected PolymorphicListXmlSerializer() {
        super(List.class);
    }

    @Override
    public void serialize(List<?> list, JsonGenerator gen, SerializerProvider provider) throws IOException {
        ToXmlGenerator xmlGen = (ToXmlGenerator) gen;
        for (Object item : list) {
            if (item == null) {
                continue;
            }
            // 根据元素类型获取对应的XML标签名
            String tagName = getTagNameByType(item.getClass());
            // 设置当前元素的XML标签名
            xmlGen.setNextName(tagName);
            // 序列化元素内容
            provider.defaultSerializeValue(item, gen);
        }
    }

    // 自定义类型到标签名的映射逻辑,可按需扩展
    private String getTagNameByType(Class<?> clazz) {
        if (Foo.class.isAssignableFrom(clazz)) {
            return "Foo";
        } else if (Bar.class.isAssignableFrom(clazz)) {
            return "Bar";
        }
        // 默认返回类名,也可抛出异常处理未知类型
        return clazz.getSimpleName();
    }
}
  1. 序列化后生成的XML结构与SimpleXML的输出完全一致。

这种方式可以处理更复杂的场景,比如动态生成标签名、处理未知类型等。


内容的提问来源于stack exchange,提问作者Henrik Klev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 01:50:26