如何通过Jackson XmlMapper反序列化带条目包装元素的XML Map?
解决Jackson XML反序列化带包装条目的Map结构问题
是的,可以实现这种XML结构的反序列化。你遇到的问题源于对@JacksonXmlElementWrapper的用法误解——这个注解的作用是给集合/Map添加外层包装元素,而非指定每个条目的元素名。要处理<MyEntry>包裹键值对的结构,只需结合MixIn(因无法修改原POJO)和Jackson XML模块的配置即可。
解决方案步骤
1. 配置XmlMapper的XML模块
通过DefaultXmlModule指定Map条目、键、值对应的XML元素名,让Jackson明确如何映射<MyEntry>、<Key>、<Value>到Map的键值对:
XmlMapper xmlMapper = new XmlMapper(); DefaultXmlModule xmlModule = new DefaultXmlModule(); // 指定Map的每个条目对应XML元素名:MyEntry xmlModule.setMapEntryName("MyEntry"); // 指定Map键对应XML元素名:Key xmlModule.setMapKeyName("Key"); // 指定Map值对应XML元素名:Value xmlModule.setMapValueName("Value"); xmlMapper.registerModule(xmlModule); // 保持默认的未知属性校验 xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
2. 使用MixIn补充必要注解
因无法修改原MyRoot类,创建MixIn类给myMap字段添加注解,告知Jackson<MyMap>是Map的外层容器,且内部直接包含条目元素(无需额外包装):
abstract class MyRootMixIn { @JacksonXmlProperty(localName = "MyMap") @JacksonXmlElementWrapper(useWrapping = false) // 禁用Jackson自动生成的Map外层包装,<MyMap>已作为外层 Map<String, String> myMap; @JacksonXmlProperty(localName = "MyString") String myString; }
给XmlMapper注册该MixIn:
xmlMapper.addMixIn(MyRoot.class, MyRootMixIn.class);
3. 验证修改后的测试代码
更新测试逻辑,应用上述配置后即可正确解析XML:
@Test public void reproducesDeserializationIssue() throws JsonProcessingException { XmlMapper xmlMapper = new XmlMapper(); DefaultXmlModule xmlModule = new DefaultXmlModule(); xmlModule.setMapEntryName("MyEntry"); xmlModule.setMapKeyName("Key"); xmlModule.setMapValueName("Value"); xmlMapper.registerModule(xmlModule); xmlMapper.addMixIn(MyRoot.class, MyRootMixIn.class); xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true); MyRoot myRoot = xmlMapper.readValue(XML, MyRoot.class); assertEquals("abc", myRoot.getMyString()); assertEquals(2, myRoot.getMyMap().size()); // 正确识别2个条目 assertEquals("value1", myRoot.getMyMap().get("key1")); assertEquals("value2", myRoot.getMyMap().get("key2")); // 序列化验证:输出符合原XML结构 System.out.println(xmlMapper.writeValueAsString(myRoot)); }
原代码出错原因
原代码中,Jackson默认将<MyMap>下的<MyEntry>当作Map的键,值为空字符串——因为它不知道<MyEntry>内部的<Key>和<Value>才是真正的键值对。通过模块配置指定键值元素名,再结合MixIn禁用多余包装,就能让Jackson正确解析嵌套结构。
额外说明
如果需要处理更复杂的键值类型,可自定义Map反序列化器,但上述方案无需编写自定义逻辑,完全符合你“仅配置XmlMapper和使用MixIn”的需求。
内容的提问来源于stack exchange,提问作者Dmitriy Sukharev
相关产品推荐
相关产品推荐

