包含列表的数据如何使用Jackson实现XML与JSON的正确双向互转
问题根因
你使用的setDefaultUseWrapper(true)配置仅对POJO类的序列化/反序列化流程生效,当前直接基于JsonNode树模型做格式转换时,该配置不会触发列表包裹标签的生成。序列化输出的XML里多个平级的<a>标签在反序列化时会被覆盖,最终只保留最后一个元素。
解决方案
方案一:使用POJO绑定(推荐,兼容性最高)
该方案可以让defaultUseWrapper配置正常生效,是Jackson官方推荐的XML处理方式。
- 定义对应的POJO类,可通过注解自定义生成的XML标签名:
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import java.util.List; // 外层根对象 public class Root { // 自定义列表包裹标签名、子元素标签名 @JacksonXmlElementWrapper(localName = "a") @JacksonXmlProperty(localName = "item") private List<Item> a; // 补全getter、setter方法 public List<Item> getA() { return a; } public void setA(List<Item> a) { this.a = a; } } // 列表元素对象 public class Item { private Integer b; private Boolean c; private String d; // 补全getter、setter方法 public Integer getB() { return b; } public void setB(Integer b) { this.b = b; } public Boolean getC() { return c; } public void setC(Boolean c) { this.c = c; } public String getD() { return d; } public void setD(String d) { this.d = d; } }
- 修改转换逻辑,走对象绑定流程而非直接操作树模型:
private static final ObjectMapper jsonMapper = new ObjectMapper(); private static final XmlMapper xmlMapper = new XmlMapper() // 该配置默认即为true,可按需省略 .setDefaultUseWrapper(true); public static final String jsonToXml(String json) throws Exception { Root root = jsonMapper.readValue(json, Root.class); return xmlMapper.writeValueAsString(root); } public static final String xmlToJson(String xml) throws Exception { Root root = xmlMapper.readValue(xml, Root.class); return jsonMapper.writeValueAsString(root); }
运行后生成的XML会自动携带列表包裹标签,反序列化时可以正确识别为数组结构,最终转换得到的JSON和原始输入一致。
方案二:保留树模型的适配方案
如果必须使用JsonNode做转换,需要额外调整XML序列化、反序列化的特性开关适配2.9.4版本:
import com.fasterxml.jackson.dataformat.xml.FromXmlParser; import com.fasterxml.jackson.dataformat.xml.ToXmlGenerator; private static final ObjectMapper jsonMapper = new ObjectMapper(); private static final XmlMapper xmlMapper = new XmlMapper() // 开启序列化时自动包裹数组元素 .enable(ToXmlGenerator.Feature.WRITE_ARRAY_ELEMENTS_WRAPPED) // 开启反序列化时将重复标签识别为数组 .enable(FromXmlParser.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) .setDefaultUseWrapper(true);
该方案存在版本兼容性风险,优先推荐使用方案一。
内容的提问来源于stack exchange,提问作者marciel.deg
相关产品推荐
相关产品推荐

