如何用Jackson Databind在Java中序列化自定义XML标签序列?
解决方案:自定义Jackson XML序列化器实现交替标签输出
要解决Jackson XML默认将同类型标签分组输出的问题,你需要自定义Item类的序列化器,手动控制<A>和<B>标签的输出顺序,完全按照遗留系统要求的结构生成XML。
步骤1:编写自定义XML序列化器
创建一个继承自StdSerializer<Item>的序列化器,在serialize方法中手动拼接所有XML元素,包括交替输出的<A>和<B>标签:
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; import java.util.ArrayList; import java.util.List; public class ItemXmlSerializer extends StdSerializer<Item> { protected ItemXmlSerializer() { super(Item.class); } @Override public void serialize(Item item, JsonGenerator gen, SerializerProvider provider) throws IOException { ToXmlGenerator xmlGen = (ToXmlGenerator) gen; // 写入根标签<Item> xmlGen.writeStartElement("Item"); // 输出固定字段SNO和Weight xmlGen.writeStartElement("SNO"); xmlGen.writeString(item.getSNo()); xmlGen.writeEndElement(); xmlGen.writeStartElement("Weight"); xmlGen.writeNumber(item.getWeight()); xmlGen.writeEndElement(); // 根据业务逻辑生成<A>和<B>的交替序列 List<LabeledElement> mixedElements = getMixedElements(item); // 遍历写入所有<A>和<B>标签 for (LabeledElement elem : mixedElements) { xmlGen.writeStartElement(elem.getLabel()); xmlGen.writeString(elem.getValue()); xmlGen.writeEndElement(); } // 关闭根标签 xmlGen.writeEndElement(); } // 核心逻辑:根据业务需求组装<A>和<B>的输出顺序 private List<LabeledElement> getMixedElements(Item item) { List<LabeledElement> elements = new ArrayList<>(); int bIndex = 0; List<String> aList = item.getaList(); List<String> bList = item.getbList(); // 示例逻辑:匹配你提供的XML结构,每个<B>对应前面的一组<A> // 你需要根据实际业务规则修改这段逻辑,比如通过额外字段记录<B>对应的<A>位置 for (int i = 0; i < aList.size(); i++) { elements.add(new LabeledElement("A", aList.get(i))); // 匹配示例中的<B>位置:第1个<A>后是<B>foo1,第3个<A>后是<B>foo3,第6个<A>后是<B>foo6 if (bIndex < bList.size()) { if ((i == 0 && bIndex == 0) || (i == 2 && bIndex == 1) || (i == 5 && bIndex == 2)) { elements.add(new LabeledElement("B", bList.get(bIndex))); bIndex++; } } } return elements; } // 辅助类:存储标签名和对应值 private static class LabeledElement { private String label; private String value; public LabeledElement(String label, String value) { this.label = label; this.value = value; } public String getLabel() { return label; } public String getValue() { return value; } } }
步骤2:在Item类上指定序列化器
修改你的Item POJO,添加@JsonSerialize注解指定使用自定义序列化器:
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import lombok.Data; import java.util.List; @Data @JacksonXmlRootElement(localName = "Item") @JsonSerialize(using = ItemXmlSerializer.class) // 指定自定义序列化器 public class Item { @JacksonXmlProperty(localName = "SNO") private String sNo; @JacksonXmlProperty(localName = "Weight") private Float weight; @JacksonXmlProperty(localName = "A") private List<String> aList; // 可去掉@JacksonXmlElementWrapper,序列化器会手动处理 @JacksonXmlProperty(localName = "B") private List<String> bList; // 同上 }
关键说明
- 核心是
getMixedElements方法,你需要根据实际业务逻辑调整这段代码:比如如果<B>和<A>是一一配对,或者<B>对应前面N个<A>,都要在这里实现对应的组装逻辑。 - 自定义序列化器完全绕过了Jackson默认的列表分组逻辑,直接按照你需要的顺序写入XML标签,确保输出结构和遗留系统完全一致。
- 反序列化逻辑你已经实现,无需改动,只需要保证序列化时使用这个自定义序列化器即可。
内容的提问来源于stack exchange,提问作者rahulkesharwani
相关产品推荐
相关产品推荐

