我再次向外部元数据映射文件提出有关Eclipselink / MOXy的问题。
我有一个适用于类的引用xml。此xml包含适用于某些但不总是该类可以包含的所有属性的数据。
我还为日期字段设置了自定义日期时间适配器。
我的问题是我解组的xml不包含endDate属性的任何数据,但是当我做这个简单的测试时:
该属性endDate(由于尚未设置,因此不应编组)被编组为09/01/2012 17:05:28(它总是被编组为当前时间的新Date())。 / p>
以下是XML元数据文件示例:
<?xml version="1.0"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
version="2.1">
<java-types>
<java-type name="sample.clazz.Task" xml-accessor-type="NONE">
<xml-root-element name="Task" />
<xml-type prop-order="startDate endDate id ci ch cr" />
<java-attributes>
<xml-element java-attribute="startDate" xml-path="StartDate/text()">
<xml-java-type-adapter value="utils.JaxBDateTimeAdapter" type="java.util.Date"/>
</xml-element>
<xml-element java-attribute="endDate" required="false" xml-path="EndDate/text()">
<xml-java-type-adapter value="utils.JaxBDateTimeAdapter" type="java.util.Date"/>
</xml-element>
<xml-element java-attribute="id" xml-path="TaskId/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()" />
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
这是班级:
package sample.clazz;
public class Task{
private int id;
private Date startDate;
private Date endDate;
private String ci;
private String ch;
private String cr;
public Task(){
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
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;
}
}
这是我的自定义DateTimeAdapter:
package utils;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class JaxBDateTimeAdapter extends XmlAdapter<String, Date> {
@Override
public String marshal(Date d) throws Exception {
if(d != null){
return DateUtil.getFormatedDateTimeString(d);
}
else{
return null;
}
}
@Override
public Date unmarshal(String d) throws Exception {
if(d != null && !"".equals(d)){
return DateUtil.getDateFromString(d);
}
else{
return null;
}
}
}
这是我的参考XML
<?xml version="1.0" encoding="UTF-8"?>
<Task>
<TaskId>147</TaskId>
<CRPR>0087</CRPR>
<CIPR>A683557</CIPR>
<CHPR>BV</CHPR>
<StartDate>22/01/2009 20:56:29</StartDate>
</Task>
这是我在重新编组对象时得到的XML:
<?xml version="1.0" encoding="UTF-8"?>
<Task>
<TaskId>147</TaskId>
<CRPR>0087</CRPR>
<CIPR>A683557</CIPR>
<CHPR>BV</CHPR>
<StartDate>01/01/2012 20:56:29</StartDate>
<EndDate>09/01/2012 17:05:28</EndDate> <!-- That element should not exist ! -->
</Task>
似乎Jaxb为空字段生成了一个新日期,如何通过外部元数据映射文件告诉他不要为空值或空值生成节点?我试图在元数据文件上设置required = false,如果值为null,我尝试使用自定义DateTimeAdapter进行测试,但似乎Jaxb创建了一个新的Date对象并将其传递给适配器的marshal方法。我想不出任何阻止他这样做的方法。
至于我以前的问题,我无法控制传入的XML或模型类。
请注意:这些数据是我写的样本,可能不准确,因为我无法公开实际数据或名称,可能会有一些输入错误。
感谢您的帮助。
答案 0 :(得分:2)
我是EclipseLink JAXB (MOXy)领导,但我无法重现您的问题。您的DateUtil
课程可能存在问题。以下是我的尝试:
<强> oxm.xml 强>
我对您的元数据文件做了一些小改动。基本上我更改了它以指定xml-bindings
元素上的包名称而不是单个java-type
元素:
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
version="2.3"
package-name="sample.clazz">
<java-types>
<java-type name="Task" xml-accessor-type="NONE">
<xml-root-element name="Task" />
<xml-type prop-order="startDate endDate id ci ch cr" />
<java-attributes>
<xml-element java-attribute="startDate" xml-path="StartDate/text()">
<xml-java-type-adapter value="forum8791782.JaxBDateTimeAdapter" type="java.util.Date"/>
</xml-element>
<xml-element java-attribute="endDate" required="false" xml-path="EndDate/text()">
<xml-java-type-adapter value="forum8791782.JaxBDateTimeAdapter" type="java.util.Date"/>
</xml-element>
<xml-element java-attribute="id" xml-path="TaskId/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()" />
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
<强> DateUtil 强>
您未在问题中提供DateUtil
的实施,因此我使用了以下内容。我猜你的DateUtil
实现中的代码会导致你看到的输出:
package forum8791782;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil {
private static SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
public static String getFormatedDateTimeString(Date d) {
return formatter.format(d);
}
public static Date getDateFromString(String d) {
try {
return formatter.parse(d);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
<强>演示强>
以下是我用来运行此示例的代码。 input.xml
是您在问题中引用的参考XML:
package forum8791782;
import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.Version;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import sample.clazz.Task;
public class Demo {
public static void main(String[] args) throws Exception {
System.out.println(Version.getVersionString());
Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum8791782/oxm.xml");
JAXBContext jc = JAXBContext.newInstance(new Class[] {Task.class}, properties);
File xml = new File("src/forum8791782/input.xml");
Unmarshaller u = jc.createUnmarshaller();
Task task = (Task) u.unmarshal(xml);
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(task, System.out);
}
}
<强>输出强>
以下是我从运行示例代码得到的输出。我没有看到写出EndDate
元素。
2.3.2.v20111125-r10461
<?xml version="1.0" encoding="UTF-8"?>
<Task>
<StartDate>22/01/2009 20:56:29</StartDate>
<TaskId>147</TaskId>
<CIPR>A683557</CIPR>
<CHPR>BV</CHPR>
<CRPR>0087</CRPR>
</Task>