如何用Jackson反序列化任意深度的递归嵌套XML?
用Jackson注解处理递归嵌套XML结构并收集带完整组链的对象
一、先修正XML拼写错误
你提供的XML存在两处拼写错误,会导致解析失败,需先修正:
<gropup>→<group></goups>→</groups>
修正后的XML示例:
<root> <groups> <group> <group_data>...group data level 1...</group_data> <object>object 1-1</object> <object>object 1-2</object> <groups> <group> <group_data>...group data level 2...</group_data> <object>object 2-1</object> <groups> <group> <group_data>...group data level 3-1...</group_data> <object>object 3-1-1</object> <object>object 3-1-2</object> </group> <group> <group_data>...group data level 3-2...</group_data> <object>object 3-2-1</object> </group> </groups> </group> </groups> </group> </groups> </root>
二、引入Jackson XML依赖
需添加Jackson的XML解析模块,Maven依赖示例:
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.15.2</version> <!-- 使用最新稳定版 --> </dependency>
三、用Jackson注解完善Java类结构
1. Root类(对应XML根节点)
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.util.List; @JacksonXmlRootElement(localName = "root") public class Root { @JacksonXmlElementWrapper(localName = "groups") @JacksonXmlProperty(localName = "group") private List<Group> groups; // Getter & Setter public List<Group> getGroups() { return groups; } public void setGroups(List<Group> groups) { this.groups = groups; } }
2. Group类(递归核心类)
修正字段命名规范并添加XML映射注解:
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import java.util.List; public class Group { @JacksonXmlProperty(localName = "group_data") private String groupData; @JacksonXmlElementWrapper(localName = "groups") @JacksonXmlProperty(localName = "group") private List<Group> groups; @JacksonXmlElementWrapper(useWrapping = false) // 直接映射<object>节点,无需外层包装 @JacksonXmlProperty(localName = "object") private List<Item> items; // Getter & Setter public String getGroupData() { return groupData; } public void setGroupData(String groupData) { this.groupData = groupData; } public List<Group> getGroups() { return groups; } public void setGroups(List<Group> groups) { this.groups = groups; } public List<Item> getItems() { return items; } public void setItems(List<Item> items) { this.items = items; } }
3. Item与ItemData类
用@JacksonXmlText映射XML节点的文本内容:
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText; public class Item { private ItemData item; // Getter & Setter public ItemData getItem() { return item; } public void setItem(ItemData item) { this.item = item; } } class ItemData { @JacksonXmlText private String itemName; // Getter & Setter public String getItemName() { return itemName; } public void setItemName(String itemName) { this.itemName = itemName; } }
四、解析XML并收集带完整组链的对象
解析完成后,递归遍历Group结构,为每个Item收集从根到当前Group的完整groupData链:
import com.fasterxml.jackson.dataformat.xml.XmlMapper; import java.io.File; import java.util.ArrayList; import java.util.List; public class XmlParser { public static void main(String[] args) throws Exception { XmlMapper xmlMapper = new XmlMapper(); Root root = xmlMapper.readValue(new File("your-xml-file.xml"), Root.class); List<ItemWithGroupChain> result = new ArrayList<>(); if (root.getGroups() != null) { for (Group rootGroup : root.getGroups()) { traverseGroup(rootGroup, new ArrayList<>(), result); } } // 输出结果示例 for (ItemWithGroupChain itemChain : result) { System.out.println("组链:" + String.join(" → ", itemChain.getGroupDataChain())); System.out.println("对象:" + itemChain.getItemData().getItemName()); System.out.println("---"); } } private static void traverseGroup(Group currentGroup, List<String> parentChain, List<ItemWithGroupChain> result) { List<String> currentChain = new ArrayList<>(parentChain); currentChain.add(currentGroup.getGroupData()); // 收集当前组下的所有对象 if (currentGroup.getItems() != null) { for (Item item : currentGroup.getItems()) { result.add(new ItemWithGroupChain(currentChain, item.getItem())); } } // 递归遍历子组 if (currentGroup.getGroups() != null) { for (Group subGroup : currentGroup.getGroups()) { traverseGroup(subGroup, currentChain, result); } } } // 辅助类:存储对象与对应组链 static class ItemWithGroupChain { private List<String> groupDataChain; private ItemData itemData; public ItemWithGroupChain(List<String> groupDataChain, ItemData itemData) { this.groupDataChain = groupDataChain; this.itemData = itemData; } public List<String> getGroupDataChain() { return groupDataChain; } public ItemData getItemData() { return itemData; } } }
关键注解说明
@JacksonXmlRootElement:指定Java类对应的XML根节点名称@JacksonXmlElementWrapper:处理集合的包装节点,useWrapping=false表示集合元素直接作为父节点的子节点@JacksonXmlProperty:映射Java字段与XML节点名称,解决命名风格差异@JacksonXmlText:将XML节点的文本内容绑定到Java字段
内容的提问来源于stack exchange,提问作者r00tGER
相关产品推荐
相关产品推荐

