Java中使用Jackson XML Databind生成指定格式SOAP XML请求的问题求助
我来帮你搞定这个Jackson XML序列化SOAP请求的问题!你遇到的核心问题是命名空间配置错误、对象结构冗余,导致生成的XML不符合要求且出现解析异常。下面是修正后的完整实现:
正确的Java类结构
我们将通过合理的注解配置和对象结构,精准生成你需要的SOAP XML格式。
1. SOAP根节点:Envelope
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @JacksonXmlRootElement(localName = "Envelope", namespace = "s") public class SoapEnvelope { // 定义xmlns:s属性 @JacksonXmlProperty(isAttribute = true, namespace = "xmlns") private String s = "http://schemas.xmlsoap.org/soap/envelope/"; @JacksonXmlProperty(localName = "Body", namespace = "s") private SoapBody body; // Getters & Setters public SoapBody getBody() { return body; } public void setBody(SoapBody body) { this.body = body; } }
2. SOAP Body节点
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public class SoapBody { // 直接定义xmlns:xsi和xmlns:xsd属性 @JacksonXmlProperty(isAttribute = true, localName = "xmlns:xsi") private String xsi = "http://www.w3.org/2001/XMLSchema-instance"; @JacksonXmlProperty(isAttribute = true, localName = "xmlns:xsd") private String xsd = "http://www.w3.org/2001/XMLSchema"; // 支持两种请求类型:authenticate和getFullCustomerInfo private Authenticate authenticate; private GetFullCustomerInfo getFullCustomerInfo; // Getters & Setters public Authenticate getAuthenticate() { return authenticate; } public void setAuthenticate(Authenticate authenticate) { this.authenticate = authenticate; } public GetFullCustomerInfo getGetFullCustomerInfo() { return getFullCustomerInfo; } public void setGetFullCustomerInfo(GetFullCustomerInfo getFullCustomerInfo) { this.getFullCustomerInfo = getFullCustomerInfo; } }
3. 通用带空命名空间的元素类
用来生成<xxx xmlns="">...</xxx>格式的节点,避免重复代码:
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText; public class XmlElementWithEmptyNamespace { @JacksonXmlProperty(isAttribute = true, localName = "xmlns") private String xmlns = ""; // 用@JacksonXmlText标记该类的value为元素文本内容,而非子节点 @JacksonXmlText private String value; // 构造函数 public XmlElementWithEmptyNamespace(String value) { this.value = value; } public XmlElementWithEmptyNamespace() {} // Jackson序列化需要无参构造 // Getter & Setter public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
4. Authenticate请求节点
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public class Authenticate { @JacksonXmlProperty(isAttribute = true, localName = "xmlns") private String xmlns = "YOUR_REQUEST_ENDPOINT"; // 替换为实际请求端点 private XmlElementWithEmptyNamespace userName; private XmlElementWithEmptyNamespace password; // Getters & Setters public XmlElementWithEmptyNamespace getUserName() { return userName; } public void setUserName(XmlElementWithEmptyNamespace userName) { this.userName = userName; } public XmlElementWithEmptyNamespace getPassword() { return password; } public void setPassword(XmlElementWithEmptyNamespace password) { this.password = password; } }
5. GetFullCustomerInfo请求节点
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public class GetFullCustomerInfo { @JacksonXmlProperty(isAttribute = true, localName = "xmlns") private String xmlns = "YOUR_REQUEST_ENDPOINT"; // 替换为实际请求端点 private XmlElementWithEmptyNamespace customerNumber; private XmlElementWithEmptyNamespace sessionKey; // Getters & Setters public XmlElementWithEmptyNamespace getCustomerNumber() { return customerNumber; } public void setCustomerNumber(XmlElementWithEmptyNamespace customerNumber) { this.customerNumber = customerNumber; } public XmlElementWithEmptyNamespace getSessionKey() { return sessionKey; } public void setSessionKey(XmlElementWithEmptyNamespace sessionKey) { this.sessionKey = sessionKey; } }
序列化测试代码
import com.fasterxml.jackson.dataformat.xml.XmlMapper; import java.io.IOException; public class SoapSerializerTest { public static void main(String[] args) throws IOException { XmlMapper xmlMapper = new XmlMapper(); xmlMapper.enable(com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator.Feature.WRITE_XML_DECLARATION); // 生成authenticate请求 SoapEnvelope authEnvelope = new SoapEnvelope(); SoapBody authBody = new SoapBody(); Authenticate auth = new Authenticate(); auth.setUserName(new XmlElementWithEmptyNamespace("YOUR_USERNAME")); auth.setPassword(new XmlElementWithEmptyNamespace("YOUR_PASSWORD")); authBody.setAuthenticate(auth); authEnvelope.setBody(authBody); String authXml = xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(authEnvelope); System.out.println("Authenticate Request:\n" + authXml); // 生成getFullCustomerInfo请求 SoapEnvelope customerEnvelope = new SoapEnvelope(); SoapBody customerBody = new SoapBody(); GetFullCustomerInfo customerReq = new GetFullCustomerInfo(); customerReq.setCustomerNumber(new XmlElementWithEmptyNamespace("YOUR_CUSTOMER_NUMBER")); customerReq.setSessionKey(new XmlElementWithEmptyNamespace("YOUR_SESSION_KEY")); customerBody.setGetFullCustomerInfo(customerReq); customerEnvelope.setBody(customerBody); String customerXml = xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(customerEnvelope); System.out.println("\nGet Full Customer Info Request:\n" + customerXml); } }
错误原因解析
- 重复xmlns属性异常:之前你在
AuthenticationRequestBody中试图用两个@JacksonXmlProperty配置xmlns属性,Jackson会判定为重复属性。正确做法是直接用localName="xmlns:xsi"和localName="xmlns:xsd"定义命名空间属性。 - 嵌套节点错误:之前为
userName和password创建的类中又定义了同名字段,导致生成嵌套结构。使用@JacksonXmlText可以将类的value直接作为元素文本内容,避免不必要的嵌套。 - 命名空间前缀配置错误:根节点Envelope的namespace应设置为
s,同时通过namespace="xmlns"定义xmlns:s属性,而非之前的错误配置。
内容的提问来源于stack exchange,提问作者LordCommander
相关产品推荐
相关产品推荐

