java - 使用 JAXB 通过 SOAP 传递 HashMap<String,Object>

标签 java soap jaxb schema wsdl2java

我正在尝试通过 SOAP 传递 HashMap 。我正在使用 CXF wsdl2java 来创建我的模式。而且我已经为我的 HashMap 创建了一个包装器类,因为 Hashmap 本身不能通过线路传递。

然后我创建了适配器以将该 Hashmap 转变为我的 wsdl 的已知类型,但是当我的 wsdl 创建时它添加了一些不需要的抽象映射。下面是代码:

这是我的 HashMap 包装器类

@XmlRootElement(name = "testTO")
public class TestTO {

    private HashMap<String, Object> mapTest;

    public TestTO(){
        this.mapTest = new HashMap<String, Object>();
    }

    @XmlJavaTypeAdapter(MapAdapter.class)
    public HashMap<String, Object> getMapTest() {
        return mapTest;
    }

    public void setMapTest(HashMap<String, Object> mapTest) {
        this.mapTest = mapTest;
    }

}

这是 MyMap 类,其中有一个已知的模式类型

@XmlJavaTypeAdapter(MapAdapter.class)
public class MyMap extends HashMap<String, Object>{
    public final List<Entry> entryList = new ArrayList<Entry>();
}

这是上面列表中包含的条目类:

public class Entry {

    @XmlAttribute
    public String key;

    @XmlElements({
            @XmlElement(name = "byte", type = byte.class),
            @XmlElement(name = "short", type = short.class),
            @XmlElement(name = "int", type = int.class),
            @XmlElement(name = "long", type = long.class),
            @XmlElement(name = "float", type = float.class),
            @XmlElement(name = "double", type = double.class),
            @XmlElement(name = "char", type = char.class),
            @XmlElement(name = "boolean", type = boolean.class),

            @XmlElement(name = "ByteWrapper", type = Byte.class),
            @XmlElement(name = "ShortWrapper", type = Short.class),
            @XmlElement(name = "IntegerWrapper", type = Integer.class),
            @XmlElement(name = "LongWrapper", type = Long.class),
            @XmlElement(name = "FloatWrapper", type = Float.class),
            @XmlElement(name = "DoubleWrapper", type = Double.class),
            @XmlElement(name = "Character", type = Character.class),
            @XmlElement(name = "BooleanWrapper", type = Boolean.class),

            @XmlElement(name = "BigDecimal", type = BigDecimal.class),
            @XmlElement(name = "String", type = String.class),
            @XmlElement(name = "Date", type = Date.class)
    })
    public Object value;

    public Entry() {
        this.key = null;
        this.value = null;
    }

    public Entry(String key, Object value) {
        this.key = key;
        this.value = value;
    }

    public String getKey() {
        return key;
    }

    public Object getValue() {
        return value;
    }

}

这是我的适配器:

public class MapAdapter extends XmlAdapter<MyMap, Map<String, Object>> {

    @Override
    public MyMap marshal(Map<String, Object> v) throws Exception {
        MyMap myMap = new MyMap();

        for ( Map.Entry<String, Object> e : v.entrySet() ) {
            Entry entry = new Entry();
            entry.key = e.getKey();
            entry.value = e.getValue();

            myMap.entryList.add(entry);
        }
        return myMap;
    }

    @Override
    public Map<String, Object> unmarshal(MyMap v) throws Exception {
         Map<String, Object> map = new HashMap<String,Object>();
            for ( Entry e : v.entryList ) {
                map.put(e.key, e.value);
            }
     return map;
    }

}

但我的 wsdl 正在生成以下内容:

<xs:element minOccurs="0" name="foo" type="tns:testTO"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="testTO">
<xs:sequence>
<xs:element minOccurs="0" name="mapTest" type="tns:myMap"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="myMap">
<xs:complexContent>
<xs:extension base="tns:hashMap">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="entryList" nillable="true" type="tns:entry"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="hashMap">
<xs:complexContent>
<xs:extension base="tns:abstractMap">
<xs:sequence/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType abstract="true" name="abstractMap">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="entry">
<xs:sequence>
<xs:choice minOccurs="0">
<xs:element name="byte" type="xs:byte"/>
<xs:element name="short" type="xs:short"/>
<xs:element name="int" type="xs:int"/>
<xs:element name="long" type="xs:long"/>
<xs:element name="float" type="xs:float"/>
<xs:element name="double" type="xs:double"/>
<xs:element name="char" type="xs:unsignedShort"/>
<xs:element name="boolean" type="xs:boolean"/>
<xs:element name="ByteWrapper" type="xs:byte"/>
<xs:element name="ShortWrapper" type="xs:short"/>
<xs:element name="IntegerWrapper" type="xs:int"/>
<xs:element name="LongWrapper" type="xs:long"/>
<xs:element name="FloatWrapper" type="xs:float"/>
<xs:element name="DoubleWrapper" type="xs:double"/>
<xs:element name="Character" type="xs:unsignedShort"/>
<xs:element name="BooleanWrapper" type="xs:boolean"/>
<xs:element name="BigDecimal" type="xs:decimal"/>
<xs:element name="String" type="xs:string"/>
<xs:element name="Date" type="xs:dateTime"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="key" type="xs:string"/>
</xs:complexType>

我查看了我在这里发现的其他多个案例,但没有一个能够解决我的问题,我什至引用了 http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html 但是 java 的 wsdl 似乎把模式搞乱了。

谢谢。

最佳答案

我相信您不必编写自定义 XmlAdapter编码/解码 Map<String, Object使用最新的 JAXB 版本。以下示例对我来说效果很好。

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "foo")
public class Foo {
  private Map<String, Object> map = new HashMap<String, Object>();

  public Map<String, Object> getMap() {
    return params;
  }
}

这导致了一个模式:

<xs:complexType name="foo">
  <xs:sequence>
    <xs:element name="map">
      <xs:complexType>
        <xs:sequence>
          <xs:element maxOccurs="unbounded" minOccurs="0" name="entry">
            <xs:complexType>
              <xs:sequence>
                <xs:element minOccurs="0" name="key" type="xs:string"/>
                <xs:element minOccurs="0" name="value" type="xs:anyType"/>
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
      </xs:complexType>
    </xs:element>
  </xs:sequence>
</xs:complexType>

然后您应该能够解码以下 xml:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://your.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <soapenv:Header/>
   <soapenv:Body>
      <foo>
        <params>
            <entry>
               <key>string</key>
               <value xsi:type="xs:string">5</value>
             </entry>
             <entry>
                <key>integer</key>
                <value xsi:type="xs:int">54</value>
             </entry>
        </params>
      </foo>
   </soapenv:Body>
</soapenv:Envelope>

只是不要忘记 xs 和 xsi namespace 。您甚至可以将自定义类型作为值传递,而不仅仅是简单的 xsi 类型。然后你必须确保你已经指定了正确的 xsi:type.

关于java - 使用 JAXB 通过 SOAP 传递 HashMap<String,Object>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16086385/

相关文章:

java - 如何使用单个正则表达式从 Java/Apex 中的匹配子字符串中去除字符?

Java:WatchService 在复制内容之前得到通知

php - SOAP:HTTP 错误请求

jaxb - Gradle 中的自定义任务构建顺序

java - 使用监听器的正确方法是什么?

java - @Value注释不返回值

php - 嵌套 XML SOAP 响应 PHP

python-3.x - Python - Zeep SOAP 复杂头

java - 在对象图中检测到循环。这将导致无限深的 XML

java - 编写可使用 Set 属性转换为 Java 的 xml 模式