JaxB EclipseLink / MOXy:假设空日期作为今天的日期编组而不是没有为它编写节点

时间:2012-01-09 16:34:21

标签: jaxb eclipselink moxy

我再次向外部元数据映射文件提出有关Eclipselink / MOXy的问题。

我有一个适用于类的引用xml。此xml包含适用于某些但不总是该类可以包含的所有属性的数据。

我还为日期字段设置了自定义日期时间适配器。

我的问题是我解组的xml不包含endDate属性的任何数据,但是当我做这个简单的测试时:

  • 将xml引用到类
  • Marshall将该类转换为新的xml文件
  • 比较两个xml文件

该属性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或模型类。

请注意:这些数据是我写的样本,可能不准确,因为我无法公开实际数据或名称,可能会有一些输入错误。

感谢您的帮助。

1 个答案:

答案 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>