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

JAXB执行Unmarshalling解析SOAP XML返回重复空字段问题求助

问题根因分析

你遇到的反序列化全空的核心原因是命名空间不匹配,JAXB对XML节点的匹配是「节点名+命名空间」联合匹配,只要有一项对应不上就会忽略节点赋值,具体问题点如下:

  • Envelope类内的Header、Body字段都属于http://schemas.xmlsoap.org/soap/envelope/命名空间,未在字段上指定namespace属性,无法匹配带soapenv前缀的节点
  • Header类内的tMLHeader属于http://tml.t1m1.org/tML.Transport.xsd命名空间,未指定namespace无法匹配带ns1前缀的节点
  • Body类内的processSyncRequestResponse属于java:lsr.webservice.wisor.com命名空间,未指定namespace无法匹配节点
  • SendTimestamp字段是带时区的ISO日期格式,JAXB默认无法直接转换为Date类型,需要自定义适配器
  • 输出的JSON出现4个字段是因为JSON序列化框架同时序列化了public字段和getter方法:大写是字段名,小写是getter方法转换后生成的属性
修复代码

1. 日期格式适配器

先自定义日期适配类处理XML日期转换:

import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.text.SimpleDateFormat;
import java.util.Date;

public class XmlAdapterDate extends XmlAdapter<String, Date> {
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
    @Override
    public Date unmarshal(String v) throws Exception {
        return sdf.parse(v);
    }
    @Override
    public String marshal(Date v) throws Exception {
        return sdf.format(v);
    }
}

2. 实体类修正

Envelope类

@XmlRootElement(name="Envelope",namespace = "http://schemas.xmlsoap.org/soap/envelope/")
@XmlAccessorType(XmlAccessType.FIELD)
public class Envelope {
    @XmlElement(name = "Header", namespace = "http://schemas.xmlsoap.org/soap/envelope/")
    public Header Header;
    @XmlElement(name = "Body", namespace = "http://schemas.xmlsoap.org/soap/envelope/")
    public Body Body;

    // 原有getter/setter保留
}

Header类

@XmlAccessorType(XmlAccessType.FIELD)
public class Header {
    @XmlElement(name = "tMLHeader", namespace = "http://tml.t1m1.org/tML.Transport.xsd")
    public tMLHeader tMLHeader;

    // 原有getter/setter保留
}

tMLHeader类

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "http://tml.t1m1.org/tML.Transport.xsd")
public class tMLHeader {
    @XmlElement(namespace = "http://tml.t1m1.org/tML.Transport.xsd")
    public String TransportID;
    @XmlElement(namespace = "http://tml.t1m1.org/tML.Transport.xsd")
    public String ApplicationType;
    @XmlElement(namespace = "http://tml.t1m1.org/tML.Transport.xsd")
    public double ApplicationVersion;
    @XmlElement(namespace = "http://tml.t1m1.org/tML.Transport.xsd")
    public String From;
    @XmlElement(namespace = "http://tml.t1m1.org/tML.Transport.xsd")
    public String To;
    @XmlElement(namespace = "http://tml.t1m1.org/tML.Transport.xsd")
    @XmlJavaTypeAdapter(value = XmlAdapterDate.class)
    public Date SendTimestamp;
    @XmlElement(namespace = "http://tml.t1m1.org/tML.Transport.xsd")
    public int RetryCount;

    // 原有getter/setter保留
}

Body类

@XmlAccessorType(XmlAccessType.FIELD)
public class Body {
    @XmlElement(name = "processSyncRequestResponse", namespace = "java:lsr.webservice.wisor.com")
    public ProcessSyncRequestResponse processSyncRequestResponse;

    // 原有getter/setter保留
}

ProcessSyncRequestResponse类

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "java:lsr.webservice.wisor.com")
public class ProcessSyncRequestResponse {
    @XmlElement(name = "response")
    public String response;

    // 原有getter/setter保留
}

3. 反序列化代码优化

保险起见把所有关联类都传入JAXBContext,避免扫描遗漏:

File xml = new File("test.xml");
return (Envelope)JAXBContext
        .newInstance(Envelope.class, Header.class, Body.class, tMLHeader.class, ProcessSyncRequestResponse.class)
        .createUnmarshaller()
        .unmarshal(xml);
重复字段优化

如果要去掉JSON里小写的header/body重复字段,给Envelope类加上Jackson注解(其他序列化框架对应调整配置即可):

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
public class Envelope {
    // 原有内容不变
}

内容的提问来源于stack exchange,提问作者FoxsTail

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 00:54:06