使用Jackson将HashMap转换为无HashMap标签及特殊字符的XML
解决方案
问题分析
你的代码存在两个核心问题:
- 重复序列化导致异常转义:多次将HashMap序列化为XML字符串后再嵌套到另一个HashMap中,Jackson会对已有XML字符串再次转义,产生
<、
这类特殊字符。 - 默认Map序列化标签:Jackson的XmlMapper默认会把
HashMap序列化为<HashMap>标签,不符合你的输出要求。
修改后的代码
// 构造最内层数据结构 Map<String, String> messageMap = this.processMessage(message, dd, rawMessage, getYamlConfiguratios(fileName)); Map<String, Object> contractMasterFull = new HashMap<>(); contractMasterFull.put("Contract-Master-Full", messageMap); // 构造FCUBS内容 Map<String, Object> fcubsContent = new HashMap<>(); fcubsContent.put("FCUBS_HEADER", headers); // 直接传入headers对象,而非序列化后的字符串 fcubsContent.put("FCUBS_BODY", contractMasterFull); // 配置XmlMapper,解决转义和标签问题 XmlMapper xmlMapper = new XmlMapper(); // 禁用自动包裹根值,避免生成默认的<HashMap>标签 xmlMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false); // 关闭XML声明输出,避免重复生成<?xml...> xmlMapper.configure(SerializationFeature.WRITE_XML_DECLARATION, false); // 禁用非ASCII字符转义,避免生成
这类换行符转义 xmlMapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, false); // 启用格式化输出(可选,根据需要) xmlMapper.enable(SerializationFeature.INDENT_OUTPUT); // 序列化时指定根元素为BODY,直接输出目标结构 xmlMapper.writerWithRootName("BODY") .writeValue(new File(OUTPUT_FILE_PATH), fcubsContent);
关键调整说明
- 避免二次序列化:直接传递Map对象而非序列化后的字符串,让XmlMapper一次性处理整个结构,从根本上杜绝重复转义。
- 配置XmlMapper特性:
WRAP_ROOT_VALUE=false:关闭默认的根标签包裹,不会将Map序列化为<HashMap>。WRITE_XML_DECLARATION=false:避免输出重复的XML声明头。ESCAPE_NON_ASCII=false:禁止对换行符等非ASCII字符转义,消除
这类字符。
- 指定根元素:通过
writerWithRootName("BODY")将最外层标签设置为<BODY>,符合你的期望结构。
预期输出示例
<BODY> <FCUBS_HEADER> <!-- headers对应的子元素 --> </FCUBS_HEADER> <FCUBS_BODY> <Contract-Master-Full> <TR_UDF_Name> <info1>User Info #1</info1> <info2>User Info #2</info2> </TR_UDF_Name> <SecurityType>FOR</SecurityType> <!-- 其他字段 --> </Contract-Master-Full> </FCUBS_BODY> </BODY>
内容的提问来源于stack exchange,提问作者Aamir Sheraz
相关产品推荐
相关产品推荐

