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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 17:17:43