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

Java Jackson:如何将随机XML反序列化为Map<String,String>值并原样序列化

问题描述

需要将<Wrapper>元素下<a>元素的所有子元素读取为Wrapper类中myMap的key为"a"的字符串值,测试中遇到两类问题:

  • Test 1:使用含嵌套元素的XML字符串,Jackson反序列化后myMap中key"a"的值为空,序列化输出<Wrapper><a></a></Wrapper>,不符合预期。
  • Test 2:将<a>的子元素用CDATA包裹,反序列化能正确获取字符串值,但序列化后XML标签被转义,输出为<Wrapper><a>&lt;b&gt;&lt;c&gt;3 &amp;amp; 7 - 8 &amp;lt; 9&lt;/c&gt; &lt;/b&gt;</a></Wrapper>,而预期应为<Wrapper><a><b><c>3 &amp; 7 - 8 &lt; 9</c> </b></a></Wrapper>。

需求:实现将任意XML反序列化为Map<String,String>的字符串值,并原样序列化回初始XML格式。

解决方案

要实现这个需求,需要自定义Jackson的XML序列化/反序列化逻辑,让Map的value直接读取嵌套XML内容为字符串,且序列化时不转义标签。

1. 自定义XML反序列化器(嵌套XML转字符串)

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser;
import org.xml.sax.InputSource;
import java.io.StringWriter;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;

public class XmlStringDeserializer extends StdDeserializer<String> {
    protected XmlStringDeserializer() {
        super(String.class);
    }

    @Override
    public String deserialize(JsonParser parser, DeserializationContext ctx) throws IOException {
        FromXmlParser xmlParser = (FromXmlParser) parser;
        try {
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            StringWriter writer = new StringWriter();
            transformer.transform(new SAXSource(xmlParser.getStaxReader(), new InputSource()), new StreamResult(writer));
            return writer.toString().trim();
        } catch (Exception e) {
            throw new IOException("Failed to parse nested XML to string", e);
        }
    }
}

2. 自定义XML序列化器(字符串原样输出XML标签)

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;

public class XmlStringSerializer extends StdSerializer<String> {
    protected XmlStringSerializer() {
        super(String.class);
    }

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        ToXmlGenerator xmlGen = (ToXmlGenerator) gen;
        xmlGen.writeRawValue(value);
    }
}

3. 配置Wrapper类并绑定序列化/反序列化器

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import java.util.Map;

@JacksonXmlRootElement(localName = "Wrapper")
public class Wrapper {
    private Map<String, 
        @JsonDeserialize(using = XmlStringDeserializer.class)
        @JsonSerialize(using = XmlStringSerializer.class)
        String> myMap;

    // Getter & Setter
    public Map<String, String> getMyMap() {
        return myMap;
    }

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }
}

4. 测试验证

import com.fasterxml.jackson.dataformat.xml.XmlMapper;

public class XmlTest {
    public static void main(String[] args) throws Exception {
        XmlMapper xmlMapper = new XmlMapper();
        String inputXml = "<Wrapper><a><b><c>3 &amp; 7 - 8 &lt; 9</c> </b></a></Wrapper>";
        
        // 反序列化
        Wrapper wrapper = xmlMapper.readValue(inputXml, Wrapper.class);
        System.out.println("反序列化后myMap['a']的值:" + wrapper.getMyMap().get("a"));
        
        // 序列化回XML
        String outputXml = xmlMapper.writeValueAsString(wrapper);
        System.out.println("序列化输出XML:" + outputXml);
    }
}

核心说明

  • 反序列化器通过JAXP Transformer将嵌套XML节点完整转换为字符串,保留所有标签和实体。
  • 序列化器调用writeRawValue直接输出字符串内容,避免Jackson自动转义XML标签。
  • 使用默认XmlMapper配置即可,无需额外开启转义或特殊处理。

内容的提问来源于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.06.16 14:17:37