我是MOXy和JaxB的新手,我遇到了java.util.Date转换的问题。
我正在使用映射文件将XML文件(我无法控制)解组为对象(我既不能手动注释现有类也不能更改它们。)
我的XML映射文件如下所示:
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
version="2.1">
<java-types>
<java-type name="Observation">
<xml-type prop-order="date theoricalTime ci ch cr type" />
<java-attributes>
<xml-element java-attribute="date" xml-path="Date/text()" />
<xml-element java-attribute="theoricalTime" xml-path="TheoricalTime/text()" />
<xml-element java-attribute="ci" xml-path="CIPR/text()" />
<xml-element java-attribute="ch" xml-path="CHPR/text()" />
<xml-element java-attribute="cr" xml-path="CRPR/text()" />
<xml-element java-attribute="type" xml-path="Type/text()" />
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
在我正在编组的类中,属性“date”和“theoricalTime”的类型为java.util.Date。
我正在编组的xml中的值是具有这种格式的字符串:“dd / MM / yyyy HH:mm:ss”(“05/01/2012 16:36:24”)。我也有一些只有时间值“HH:mm:ss”(“14:17:33”)的字段。
这是我在解组文件时得到的堆栈跟踪:
Exception in thread "main" Local Exception Stack:
Exception [EclipseLink-3002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.ConversionException
Exception Description: The object [22/01/2009 20:56:29], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[date-->Date/text()]] with descriptor [XMLDescriptor(Observation --> [DatabaseTable(Observation)])], could not be converted to [class java.util.Calendar].
at org.eclipse.persistence.exceptions.ConversionException.incorrectDateTimeFormat(ConversionException.java:127)
at org.eclipse.persistence.exceptions.ConversionException.incorrectDateTimeFormat(ConversionException.java:133)
at org.eclipse.persistence.internal.oxm.XMLConversionManager.convertStringToXMLGregorianCalendar(XMLConversionManager.java:703)
at org.eclipse.persistence.internal.oxm.XMLConversionManager.convertStringToDate(XMLConversionManager.java:1111)
at org.eclipse.persistence.internal.oxm.XMLConversionManager.convertObjectToUtilDate(XMLConversionManager.java:804)
at org.eclipse.persistence.internal.oxm.XMLConversionManager.convertObject(XMLConversionManager.java:165)
at org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform.convertObject(DatasourcePlatform.java:160)
at org.eclipse.persistence.oxm.mappings.XMLDirectMapping.getAttributeValue(XMLDirectMapping.java:293)
at org.eclipse.persistence.internal.oxm.XMLDirectMappingNodeValue.endElement(XMLDirectMappingNodeValue.java:182)
at org.eclipse.persistence.oxm.record.UnmarshalRecord.endElement(UnmarshalRecord.java:823)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:601)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1774)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2930)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at org.eclipse.persistence.internal.oxm.record.XMLReader.parse(XMLReader.java:157)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:753)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:333)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:320)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:280)
at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:306)
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:115)
at Main.Test(Main.java:97)
at Main.main(Main.java:35)
我的问题是:是否可以使用MOXy的外部元数据在映射文件中指定类型转换?如何使用上面指定的格式处理日期时间并将它们映射到日期字段?
(我暗暗希望Blaise Doughan正在读这篇文章。)
提前感谢您的帮助!
答案 0 :(得分:6)
以下内容演示了如何使用XmlAdapter
和MOXy的外部映射文档来实现您正在寻找的结果:
<强> DateAdapter 强>
由于您的日期/时间数据采用以下格式dd/MM/yyyy HH:mm:ss
,因此您需要使用XmlAdapter
,如下所示:
package forum8745305;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class DateAdapter extends XmlAdapter<String, Date> {
private SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
@Override
public String marshal(Date v) throws Exception {
return dateFormat.format(v);
}
@Override
public Date unmarshal(String v) throws Exception {
return dateFormat.parse(v);
}
}
<强> oxm.xml 强>
这通常使用@XmlJavaTypeAdapter
注释在您的域模型中指定,但由于您使用的是MOXy的外部元数据文档,因此您可以按如下方式指定它。我已在包级别指定它,以便它将应用于属于该包中的域类的java.util.Date
类型的所有字段/属性:
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
version="2.1"
package-name="forum8745305">
<xml-java-type-adapters>
<xml-java-type-adapter value="forum8745305.DateAdapter" type="java.util.Date"/>
</xml-java-type-adapters>
<java-types>
<java-type name="Observation">
<xml-type prop-order="date theoricalTime ci ch cr type" />
<xml-root-element/>
<java-attributes>
<xml-element java-attribute="date" xml-path="Date/text()"/>
<xml-element java-attribute="theoricalTime" xml-path="TheoricalTime/text()" />
<xml-element java-attribute="numeroTrain" xml-path="NumeroTrain/text()" />
<xml-element java-attribute="ci" xml-path="CIPR/text()" />
<xml-element java-attribute="ch" xml-path="CHPR/text()" />
<xml-element java-attribute="cr" xml-path="CRPR/text()" />
<xml-element java-attribute="type" xml-path="Type/text()" />
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
<强>观察强>
根据您的问题,以下是您的域类的外观:
package forum8745305;
import java.util.Date;
public class Observation {
private Date date;
private Date theoricalTime;
private String numeroTrain;
private String ci;
private String ch;
private String cr;
private String type;
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Date getTheoricalTime() {
return theoricalTime;
}
public void setTheoricalTime(Date theoricalTime) {
this.theoricalTime = theoricalTime;
}
public String getNumeroTrain() {
return numeroTrain;
}
public void setNumeroTrain(String numeroTrain) {
this.numeroTrain = numeroTrain;
}
public String getCi() {
return ci;
}
public void setCi(String ci) {
this.ci = ci;
}
public String getCh() {
return ch;
}
public void setCh(String ch) {
this.ch = ch;
}
public String getCr() {
return cr;
}
public void setCr(String cr) {
this.cr = cr;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
<强>演示强>
以下代码可用于运行示例:
package forum8745305;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum8745305/oxm.xml");
JAXBContext jc = JAXBContext.newInstance(new Class[] {Observation.class}, properties);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum8745305/input.xml");
Observation observation = (Observation) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(observation, System.out);
}
}
<强>输入/输出强>
<?xml version="1.0" encoding="UTF-8"?>
<observation>
<Date>05/01/2012 16:36:24</Date>
<TheoricalTime>01/02/2012 12:34:45</TheoricalTime>
</observation>
了解更多信息
<强>更新强>
您还可以在属性级别指定XmlAdapters
。这意味着,如果您愿意,可以为每个XmlAdapter
属性设置不同的Date
。
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
version="2.1"
package-name="forum8745305">
<java-types>
<java-type name="Observation">
<xml-type prop-order="date theoricalTime ci ch cr type" />
<xml-root-element/>
<java-attributes>
<xml-element java-attribute="date" xml-path="Date/text()">
<xml-java-type-adapter value="forum8745305.DateAdapter"/>
</xml-element>
<xml-element java-attribute="theoricalTime" xml-path="TheoricalTime/text()">
<xml-java-type-adapter value="forum8745305.DateAdapter"/>
</xml-element>
<xml-element java-attribute="numeroTrain" xml-path="NumeroTrain/text()" />
<xml-element java-attribute="ci" xml-path="CIPR/text()" />
<xml-element java-attribute="ch" xml-path="CHPR/text()" />
<xml-element java-attribute="cr" xml-path="CRPR/text()" />
<xml-element java-attribute="type" xml-path="Type/text()" />
</java-attributes>
</java-type>
</java-types>
</xml-bindings>