Jackson替代SimpleXML @ElementListUnion的方案及自定义序列化实现
Jackson替代SimpleXML @ElementListUnion的方案与实现
Jackson没有提供和SimpleXML的@ElementListUnion完全等价的注解,但有两种可行的实现方式:
一、使用Jackson类型注解实现(简洁方案)
通过@JsonTypeInfo和@JsonSubTypes结合XML配置,可以直接生成按类型命名的标签,无需自定义序列化器。
代码示例
- 定义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 省略 }
- 序列化后生成的XML结构:
<Root> <Foo> {correct Foo serialization} </Foo> <Bar> {correct Bar serialization} </Bar> </Root>
这种方式适合类型固定的场景,配置简单,无需额外编写序列化逻辑。
二、自定义序列化器实现(灵活方案)
如果需要更灵活的标签名映射规则(比如动态生成标签名),可以编写自定义List序列化器,根据元素类型动态修改标签名。
代码示例
- 定义Root类,指定自定义序列化器:
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.util.List; class Root { @JsonSerialize(using = PolymorphicListXmlSerializer.class) protected List<Object> fooOrBar; // 构造方法、Getter/Setter 省略 }
- 实现自定义序列化器:
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(); } }
- 序列化后生成的XML结构与SimpleXML的输出完全一致。
这种方式可以处理更复杂的场景,比如动态生成标签名、处理未知类型等。
内容的提问来源于stack exchange,提问作者Henrik Klev
相关产品推荐
相关产品推荐

