Jackson XML无法正确解析嵌套对象,返回空对象问题求助
Hey, let's dig into this Jackson XML parsing issue you're facing. It's tricky when parts work in isolation but break in the full context—here's what I think is going on and how to fix it:
From your description, the core issue is that Group's array/struct collections come back null when parsing the full XML, but work fine when testing individual fragments. This almost always boils down to subtle mismatches between XML structure and Jackson annotations, plus potential XML validity issues that only surface in full-document parsing.
Let's break down the root causes and fixes step by step:
1. First: Fix the Invalid XML
Looking at your sample XML, there's an unclosed <define> node inside the <struct name="compatibility_"> block. When parsing the full document, this invalid structure can throw off Jackson's parser, causing it to skip or misinterpret subsequent nodes (like your <array>). When testing fragments, you probably fixed this accidentally, hence why it worked there.
Here's the corrected XML snippet:
<config> <group name="sys"> <desc>sss</desc> <define name="DYN"> <const>1</const> <desc> </desc> </define> <par name="show_time" type="ACT" len="1"> <snmp oid="1">ssss</snmp> <val>0</val> <desc>Show system</desc> </par> <struct name="compatibility_"> <desc> </desc> <par name="link" type="PAR" len="1" range="0,1"> <snmp oid="232">ssss</snmp> <val>0</val> <desc> </desc> </par> <define name="POLL_AND_INTERRUPT"> <mask>0</mask> <desc> </desc> </define> <!-- Fixed: closed this node --> </struct> <array name="DYN_STRUCT" len="1" max="32"> <struct name="script_" key="name"> <desc> </desc> <par name="name" type="STRING" len="32"> </par> </struct> </array> </group> </config>
2. Align Jackson Annotations with XML Structure
Your existing annotations are close, but missing some key details that help Jackson map nested nodes and attributes correctly.
Updated Group Class
We need to explicitly link the list fields to their XML node names, and add mappings for attributes like name that exist on the <group> node:
@Getter @Setter @JsonIgnoreProperties(ignoreUnknown = true) public class Group { // Combine wrapper and property annotations to explicitly map <array> nodes @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "array") private List<Array> array = new ArrayList<>(); @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "struct") private List<Struct> struct = new ArrayList<>(); // Map the "name" attribute on <group> @JacksonXmlProperty(isAttribute = true) private String name; // Map the <desc> child node @JacksonXmlProperty(localName = "desc") private String desc; }
Updated Array Class
The struct field needs an explicit node name mapping, and we should add mappings for the attributes on the <array> node (like name, len) to avoid parsing conflicts:
@Getter @Setter @JsonIgnoreProperties(ignoreUnknown = true) public class Array { @JacksonXmlProperty(localName = "struct") private Struct struct; @JacksonXmlProperty(isAttribute = true) private String name; @JacksonXmlProperty(isAttribute = true) private Integer len; @JacksonXmlProperty(isAttribute = true) private Integer max; }
Updated Struct Class
Keep your existing setup, but add mappings for the <struct> node's attributes and child nodes to ensure consistency:
@Getter @Setter @JsonIgnoreProperties(ignoreUnknown = true) public class Struct { @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "par") private List<Par> par = new ArrayList<>(); @JacksonXmlProperty(isAttribute = true) private String name; @JacksonXmlProperty(localName = "desc") private String desc; }
3. Parsing Code Example
Make sure you're using the XmlMapper correctly, and wrap the root <config> node in a matching class (since your XML starts with <config>):
// Define a wrapper class for the root <config> node @Getter @Setter @JsonIgnoreProperties(ignoreUnknown = true) public class Config { @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "group") private List<Group> group; } // Parse the XML XmlMapper xmlMapper = new XmlMapper(); xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); Config config = xmlMapper.readValue(yourXmlString, Config.class); Group sysGroup = config.getGroup().stream() .filter(g -> "sys".equals(g.getName())) .findFirst() .orElse(null); // Now sysGroup's array and struct lists should populate correctly
Key Verification Checks
- The invalid XML was likely the biggest culprit—full-document parsers are strict about well-formedness, while fragment testing may have overlooked the unclosed node.
- Explicitly annotating attributes and node names removes ambiguity for Jackson, which is critical when dealing with nested collections.
- Using
@JsonIgnoreProperties(ignoreUnknown = true)prevents unexpected nodes (like<define>or<par>in<group>) from breaking the parsing flow.
内容的提问来源于stack exchange,提问作者mihau7

