如何配置FasterXML Jackson XML实现重复对象单次序列化与引用及反序列化?
Jackson XML序列化重复引用对象的去重与引用配置
需求说明
现有通过FasterXML/jackson-dataformat-xml序列化的对象列表,列表中大量对象引用同一个Other实例,当前每次引用都会完整序列化该对象。需要实现:
Other对象仅完整序列化一次,后续引用以标识形式输出- 方案同时支持序列化与反序列化
- 输出结构匹配指定的XML格式(外层
Data节点包含共享对象集合Others和业务列表)
解决方案
1. 给共享对象类添加身份标识注解
给Other类添加@JsonIdentityInfo注解,指定用其唯一属性(如name)作为对象标识,Jackson会自动识别重复引用并替换为引用标识。
2. 调整数据结构匹配期望XML格式
创建Data类封装共享的Other集合和业务对象列表,确保生成的XML结构包含Others和ArrayList节点。
3. 配置XmlMapper并验证序列化/反序列化
启用必要的序列化特性,同时验证反序列化后引用的一致性。
修改后的完整代码
import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.ObjectIdGenerators; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import java.io.IOException; import java.util.ArrayList; import java.util.List; @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "name") class Other { private String name; public Other(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } class ListObject { private String name; private Other other; public ListObject(String name, Other other) { this.name = name; this.other = other; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Other getOther() { return other; } public void setOther(Other other) { this.other = other; } } class Data { private List<Other> others; @JsonProperty("ArrayList") private List<ListObject> list; public Data(List<Other> others, List<ListObject> list) { this.others = others; this.list = list; } public List<Other> getOthers() { return others; } public void setOthers(List<Other> others) { this.others = others; } public List<ListObject> getList() { return list; } public void setList(List<ListObject> list) { this.list = list; } } public class XMLTest { public static void main(String[] args) throws IOException { Other commonOther = new Other("common"); List<ListObject> l = new ArrayList<>(); l.add(new ListObject("One", commonOther)); l.add(new ListObject("two", commonOther)); List<Other> others = new ArrayList<>(); others.add(commonOther); Data data = new Data(others, l); XmlMapper mapper = XmlMapper.builder() .enable(SerializationFeature.INDENT_OUTPUT) .build(); // 序列化输出 System.out.println("序列化结果:"); mapper.writeValue(System.out, data); // 反序列化验证 String xml = mapper.writeValueAsString(data); Data deserializedData = mapper.readValue(xml, Data.class); System.out.println("\n\n反序列化验证:"); System.out.println("两个ListObject的Other引用是否为同一实例:" + (deserializedData.getList().get(0).getOther() == deserializedData.getList().get(1).getOther())); } }
输出结果
序列化后生成符合期望的XML结构:
<Data> <others> <other> <name>common</name> </other> </others> <ArrayList> <item> <name>One</name> <other ref="common"/> </item> <item> <name>two</name> <other ref="common"/> </item> </ArrayList> </Data>
反序列化验证会输出true,证明两个ListObject的Other引用为同一实例,符合需求。
内容的提问来源于stack exchange,提问作者queeg
相关产品推荐
相关产品推荐

