2017-01-18 16 views
0

Я должен взаимодействовать с веб-службы, которая WSDL содержит следующую ComplexType:JAX-WS (JAXB): Как marshall java.util.Date в xs: anyType как xs: date вместо xs: dateTime?

<complexType name="KlarigoField"> 
     <complexContent> 
      <sequence> 
      <element name="Value" type="{http://www.w3.org/2001/XMLSchema}anyType" minOccurs="0"/> 
      <element name="Metadata" type="{http://klarigo.ru/main}KlarigoFieldMetadata" minOccurs="0"/> 
      </sequence> 
     </complexContent> 
    </complexType> 

В соответствии с этой частью, JAXB генерирует следующий класс:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "KlarigoField", propOrder = { 
    "value", 
    "metadata" 
}) 
public class KlarigoField { 

    @XmlElement(name = "Value", nillable = true) 
    protected Object value; 
    @XmlElement(name = "Metadata", nillable = true) 
    protected KlarigoFieldMetadata metadata; 

    public Object getValue() { 
     return value; 
    } 

    public void setValue(Object value) { 
     this.value = value; 
    } 

    public KlarigoFieldMetadata getMetadata() { 
     return metadata; 
    } 

    public void setMetadata(KlarigoFieldMetadata value) { 
     this.metadata = value; 
    } 

} 

В ходе одной операции я должен назначить java.util.Date значение к элементу «Значение», где я получаю следующий результат:

<Value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:dateTime"> 
2017-01-25T00:00:00+03:00 
</Value> 

Но мне нужно получить оценку е типа "хз: дата", что-то вроде этого:

<Value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:date"> 
2017-01-25 
</Value> 

JAXB Маршаллова java.util.Date в xs:dateTime по умолчанию. Я прочитал, что мы можем создать пользовательский адаптер, который выводит java.util.Date в xs:date как ответил here. Проблема в том, что мы можем применить этот адаптер только к полям java.util.Date, а не к java.lang.Object (xs:anyType), причем это поле должно быть контейнером для значений разных типов. Что я могу сделать для решения моей проблемы?


UPDATE: мне удалось получить необходимый результат за счет создания пользовательского типа "дата", которая оборачивает java.util.Date:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "date", namespace = "http://www.w3.org/2001/XMLSchema", propOrder = { 
     "value" 
    }) 
    public class Date { 

     @XmlValue 
     @XmlJavaTypeAdapter(DateAdapter.class) 
     @XmlSchemaType(name = "date") 
     protected java.util.Date value; 

     public java.util.Date getValue() { 
      return value; 
     } 

     public void setValue(java.util.Date value) { 
      this.value = value; 
     } 

    } 

Дата адаптер:

public class DateAdapter extends XmlAdapter<String, Date> { 

     private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); 

     @Override 
     public Date unmarshal(String stringDate) throws Exception { 
      return DatatypeConverter.parseDate(stringDate).getTime(); 
     } 

     @Override 
     public String marshal(Date date) throws Exception { 
      synchronized (dateFormat) { 
       return dateFormat.format(date); 
      } 
     } 
    } 

я создаю объект моего настраиваемого типа, установите реальный объект java.util.Date и, наконец, установите его в поле «Значение объекта»:

my.custom.Date customDate = new my.custom.Date(); 
customDate.setValue(new java.util.Date(....)); 
klarigoField.setValue(customDate); 

Наконец, я добавил свой собственный тип Date в WSDL для автоматической генерации:

<schema targetNamespace="http://www.w3.org/2001/XMLSchema"> 
    <complexType name="date"> 
     <simpleContent> 
      <extension base="xs:date"/> 
     <simpleContent> 
    <complexType> 
<schema> 

ответ

1

Да, вы получите правильное направление, вам нужно XmlAdapter:

class DateAdapter extends XmlAdapter<String, Object> { 

    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); 

    @Override 
    public String marshal(Object v) throws Exception { 
     if (v.getClass() == Date.class) { 
      synchronized (dateFormat) { 
       return dateFormat.format(v); 
      } 
     } 
     return v.toString(); 
    } 
    // ...  
} 

И как если все ваши разные типы правильно переопределяют toString, вы можете легко маршализировать.

Подробнее:

+0

Спасибо за ответ! Я уже пытался использовать этот адаптер и применял его в поле «Значение объекта». Проблема заключалась в том, что вывод был без необходимости типа i.e xsi: type = "xs: date". Кроме того, я не смог правильно реализовать отмененный метод без маршала. –

+0

@RafaelIrgalin Я рад, что вы нашли ответ :). Извините, не помогите вам. – Tony

+0

О, нет проблем, спасибо! Ваш ответ будет полезен для других;) –