You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免Jackson XmlMapper序列化Map时转义XML特殊字符?

解决Jackson XmlMapper转义Map值中XML特殊字符的问题

这个问题我之前也碰到过——Jackson默认会把字符串里的<、>这类XML特殊字符转义成实体,因为它默认把字符串当成普通文本处理。要让嵌套的XML内容直接输出不转义,有几种可行的方案,你可以根据自己的场景选择:

方案1:用RawValue包装XML字符串(最简洁)

Jackson提供了RawValue类,专门用来标记需要直接输出、不做转义的内容。你只需要把原来的Map<String, String>转换成Map<String, Object>,将XML字符串包装成RawValue实例即可:

import com.fasterxml.jackson.databind.util.RawValue;

// 假设你的原始Map是obj
Map<String, Object> rawMap = new HashMap<>();
for (Map.Entry<String, String> entry : obj.entrySet()) {
    rawMap.put(entry.getKey(), new RawValue(entry.getValue()));
}

// 执行序列化
String xml = xmlMapper.writer().writeValueAsString(rawMap);

这样Jackson会直接把RawValue中的XML内容输出,不会转义任何特殊字符。

方案2:自定义包装类+@JacksonXmlText注解(更安全,不影响全局)

如果不想改变全局的字符串序列化行为,你可以创建一个专门的包装类,用@JacksonXmlText注解标记内容字段,告诉Jackson这是要直接输出的XML文本:

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;

public class RawXmlContent {
    @JacksonXmlText
    private String content;

    public RawXmlContent(String content) {
        this.content = content;
    }

    // 必须提供getter,Jackson需要访问字段内容
    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

然后将原始Map转换为包装类的Map:

Map<String, RawXmlContent> wrappedMap = new HashMap<>();
for (Map.Entry<String, String> entry : obj.entrySet()) {
    wrappedMap.put(entry.getKey(), new RawXmlContent(entry.getValue()));
}

String xml = xmlMapper.writer().writeValueAsString(wrappedMap);

这个方案只会影响被包装的内容,其他字符串的序列化行为保持默认,适合只有部分内容需要不转义的场景。

方案3:自定义全局字符串序列化器(不推荐,影响全局)

如果你希望所有字符串类型的内容都不转义,可以自定义一个序列化器并注册到XmlMapper中:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;

import java.io.IOException;

public class RawXmlStringSerializer extends StdSerializer<String> {

    public RawXmlStringSerializer() {
        super(String.class);
    }

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        if (gen instanceof ToXmlGenerator) {
            // 针对XML生成器,直接写入原始内容
            ((ToXmlGenerator) gen).writeRawValue(value);
        } else {
            // 非XML场景,回退到默认序列化逻辑
            gen.writeString(value);
        }
    }
}

然后注册这个序列化器:

XmlMapper xmlMapper = new XmlMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(String.class, new RawXmlStringSerializer());
xmlMapper.registerModule(module);

String xml = xmlMapper.writer().writeValueAsString(obj);

⚠️ 注意:这个方案会改变所有字符串的序列化行为,如果你的其他字符串需要正常转义(比如包含特殊字符的普通文本),会导致XML格式错误,所以除非你确定所有字符串都是原始XML,否则不建议使用。


内容的提问来源于stack exchange,提问作者Bằng Rikimaru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:14:55