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

JAXB/Jackson技术咨询:无父标签的成对元素序列POJO构建

兄弟,我之前刚好踩过类似的XML序列化坑!你说的这种和成对连续出现的场景,用Jackson确实很难搞——毕竟它对集合默认就会加包装器,就算关掉包装,也没法直接把成对的属性拆成连续的独立标签。不过用JAXB的话,通过适配器就能完美解决,给你详细说下步骤:

1. 先明确目标XML结构

假设你需要处理的XML是这种严格成对的格式:

valueA1 valueB1 valueA2 valueB2

2. 创建成对元素的POJO

先定义一个ABPair类,用来封装一组和的值:

import javax.xml.bind.annotation.XmlElement;

public class ABPair {
    private String a;
    private String b;

    @XmlElement(name = "A")
    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    @XmlElement(name = "B")
    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }
}

3. 编写JAXB适配器处理交替元素

核心是用XmlAdapter把List<ABPair>和交替的/元素做转换。先写一个临时的中间类,用来映射XML里的所有和列表:

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;

// 临时类,用于JAXB适配器的中转映射
@XmlRootElement(name = "root")
class TempRoot {
    private List<String> aList = new ArrayList<>();
    private List<String> bList = new ArrayList<>();

    @XmlElement(name = "A")
    public List<String> getaList() {
        return aList;
    }

    public void setaList(List<String> aList) {
        this.aList = aList;
    }

    @XmlElement(name = "B")
    public List<String> getbList() {
        return bList;
    }

    public void setbList(List<String> bList) {
        this.bList = bList;
    }
}

然后写适配器类,负责在List<ABPair>和TempRoot之间互相转换:

import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.util.ArrayList;
import java.util.List;

public class ABPairAdapter extends XmlAdapter<TempRoot, List<ABPair>> {

    // 把XML解析成List<ABPair>
    @Override
    public List<ABPair> unmarshal(TempRoot tempRoot) throws Exception {
        List<ABPair> pairs = new ArrayList<>();
        List<String> aList = tempRoot.getaList();
        List<String> bList = tempRoot.getbList();
        
        // 假设XML里的A和B是严格成对的,数量一致
        for (int i = 0; i < aList.size(); i++) {
            ABPair pair = new ABPair();
            pair.setA(aList.get(i));
            pair.setB(bList.get(i));
            pairs.add(pair);
        }
        return pairs;
    }

    // 把List<ABPair>序列化成XML的交替A/B元素
    @Override
    public TempRoot marshal(List<ABPair> abPairs) throws Exception {
        TempRoot tempRoot = new TempRoot();
        List<String> aList = new ArrayList<>();
        List<String> bList = new ArrayList<>();
        
        for (ABPair pair : abPairs) {
            aList.add(pair.getA());
            bList.add(pair.getB());
        }
        tempRoot.setaList(aList);
        tempRoot.setbList(bList);
        return tempRoot;
    }
}

4. 创建根节点POJO并关联适配器

最后定义根节点类,用@XmlJavaTypeAdapter指定适配器:

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.List;

@XmlRootElement(name = "root")
public class Root {
    private List<ABPair> abPairs;

    @XmlJavaTypeAdapter(ABPairAdapter.class)
    public List<ABPair> getAbPairs() {
        return abPairs;
    }

    public void setAbPairs(List<ABPair> abPairs) {
        this.abPairs = abPairs;
    }
}

5. 测试序列化/反序列化

写个简单的测试代码验证效果:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) throws Exception {
        // 构造测试数据
        Root root = new Root();
        List<ABPair> pairs = new ArrayList<>();

        ABPair pair1 = new ABPair();
        pair1.setA("valueA1");
        pair1.setB("valueB1");
        pairs.add(pair1);

        ABPair pair2 = new ABPair();
        pair2.setA("valueA2");
        pair2.setB("valueB2");
        pairs.add(pair2);

        root.setAbPairs(pairs);

        // 序列化成XML并输出
        JAXBContext context = JAXBContext.newInstance(Root.class);
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }
}

运行后就能得到你要的和成对连续的XML结构啦!

再补充下为什么Jackson不适合这个场景:Jackson的XML模块默认会给集合加包装标签,就算用@JacksonXmlElementWrapper(useWrapping = false)关掉包装,它也会把每个ABPair实例序列化成<ABPair>包裹的内容,而不是直接拆成独立的<A>和<B>标签,很难实现你要的无包装成对序列效果。所以JAXB的适配器方案是更合适的选择。

内容的提问来源于stack exchange,提问作者narendra-choudhary

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:03:22