如何将嵌套XML元素内容映射为Map的字符串值?
Jackson XML反序列化:将随机名称元素的子XML内容转为Map字符串值
使用的依赖
<dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.8.7</version> </dependency>
需求说明
需要处理如下XML,将其中名称随机的元素(例如<RandomName>,其内部内容也不固定)的元素名作为Map的key,把该元素下的所有XML内容作为字符串值存入Map,实现类似 RandomName -> <metadaten> ... </metadaten> 的映射。
示例XML
<slices> <slice> <boundedBy> <Envelope> <axisLabels>Lat Long</axisLabels> <srsDimension>2</srsDimension> <lowerCorner>-44.975 111.975</lowerCorner> <upperCorner>-8.975 130.975</upperCorner> </Envelope> </boundedBy> <local_metadata_key>test123</local_metadata_key> <RandomName> <metadaten> <Kompression>0</Kompression> <Komprimierung>0</Komprimierung> <Belaubungszustand>3</Belaubungszustand> <Bemerkungen>keine</Bemerkungen> </metadaten> </RandomName> <fileReferenceHistory>testfile</fileReferenceHistory> </slice> </slices>
当前问题
编写了LocalMetadataChild类用于反序列化,但addKeyValue()方法中,只能拿到key为RandomName,而value始终是空字符串。需要让value等于该元素下的完整子XML内容(即<metadaten> ... </metadaten>部分)。
当前代码:
public class LocalMetadataChild { public static final String LOCAL_METADATA_TAG = "slice"; private Map<String, String> localMetadataAttributesMap; private BoundedBy boundedBy; @JsonAnySetter // NOTE: To map an unknown list of properties, must use this annotation public void addKeyValue(String key, String value) { this.localMetadataAttributesMap.put(key, value); } public LocalMetadataChild() { this.localMetadataAttributesMap = new LinkedHashMap<>(); this.boundedBy = new BoundedBy(); } @JsonAnyGetter // NOTE: to unwrap the "map" from { "map": { "key": "value" } }, only keep { "key": "value" } public Map<String, String> getLocalMetadataAttributesMap() { return localMetadataAttributesMap; } public BoundedBy getBoundedBy() { return this.boundedBy; } public void setBoundedBy(BoundedBy boundedBy) { this.boundedBy = boundedBy; } public LocalMetadataChild(Map<String, String> localMetadataAttributesMap, BoundedBy boundedBy) { this.localMetadataAttributesMap = localMetadataAttributesMap; this.boundedBy = boundedBy; } }
解决方案
问题出在@JsonAnySetter的参数类型:当元素包含子XML结构时,Jackson无法直接将其序列化为String,会默认解析为内部对象,导致传入空字符串。需要修改参数类型为JsonNode,再将其序列化为XML字符串存入Map。
修改后的代码
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.dataformat.xml.XmlMapper; public class LocalMetadataChild { public static final String LOCAL_METADATA_TAG = "slice"; private Map<String, String> localMetadataAttributesMap; private BoundedBy boundedBy; private final XmlMapper xmlMapper; @JsonAnySetter public void addKeyValue(String key, JsonNode value) throws Exception { // 将JsonNode序列化为XML字符串 String xmlContent = xmlMapper.writeValueAsString(value); this.localMetadataAttributesMap.put(key, xmlContent); } public LocalMetadataChild() { this.localMetadataAttributesMap = new LinkedHashMap<>(); this.boundedBy = new BoundedBy(); this.xmlMapper = new XmlMapper(); } public LocalMetadataChild(Map<String, String> localMetadataAttributesMap, BoundedBy boundedBy) { this.localMetadataAttributesMap = localMetadataAttributesMap; this.boundedBy = boundedBy; this.xmlMapper = new XmlMapper(); } @JsonAnyGetter public Map<String, String> getLocalMetadataAttributesMap() { return localMetadataAttributesMap; } public BoundedBy getBoundedBy() { return this.boundedBy; } public void setBoundedBy(BoundedBy boundedBy) { this.boundedBy = boundedBy; } }
关键说明
- 将
@JsonAnySetter的第二个参数从String改为JsonNode,保留子元素的完整结构信息。 - 通过
XmlMapper将JsonNode重新序列化为XML字符串,存入Map即可得到目标子XML内容。 - 若不需要外层包裹节点(仅需
<metadaten>部分),可提取JsonNode的子节点后再序列化。
内容的提问来源于stack exchange,提问作者Bằng Rikimaru
相关产品推荐
相关产品推荐

