使用JAXB编组LocalDate

时间:2016-03-22 14:11:50

标签: java xml jaxb

我正在构建一系列链接类,其实例我希望能够编组为XML,这样我就可以将它们保存到文件中并稍后再读取它们。

目前我使用以下代码作为测试用例:

import javax.xml.bind.annotation.*;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import java.time.LocalDate;

public class LocalDateExample
{
  @XmlRootElement
  private static class WrapperTest {
    public LocalDate startDate;
  }

  public static void main(String[] args) throws JAXBException
  {
    WrapperTest wt = new WrapperTest();
    LocalDate ld = LocalDate.of(2016, 3, 1);
    wt.startDate = ld;
    marshall(wt);
  }

  public static void marshall(Object jaxbObject) throws JAXBException
  {
    JAXBContext context = JAXBContext.newInstance(jaxbObject.getClass());
    Marshaller marshaller = context.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    marshaller.marshal(jaxbObject, System.out);
  }
}

XML输出是:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wrapperTest>
    <startDate/>
</wrapperTest>

startDate元素为空是否有原因?我希望它包含日期的字符串表示(即toString())。为了做到这一点,我是否需要编写自己的代码?

java -version的输出是:

openjdk version "1.8.0_66-internal"
OpenJDK Runtime Environment (build 1.8.0_66-internal-b17)
OpenJDK 64-Bit Server VM (build 25.66-b17, mixed mode)

3 个答案:

答案 0 :(得分:34)

您必须像这样创建XmlAdapter

public class LocalDateAdapter extends XmlAdapter<String, LocalDate> {
    public LocalDate unmarshal(String v) throws Exception {
        return LocalDate.parse(v);
    }

    public String marshal(LocalDate v) throws Exception {
        return v.toString();
    }
}

使用

注释您的字段
 @XmlJavaTypeAdapter(value = LocalDateAdapter.class)

如果要在包级别定义适配器,请参阅javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters

答案 1 :(得分:4)

http://blog.bdoughan.com/2011/05/jaxb-and-joda-time-dates-and-times.html描述了洞穴设置。

  

Joda-Time提供了Java SE中当前提供的日期和日历类的替代方法。由于它们是在单独的库中提供的,因此JAXB不为这些类提供默认映射。

为包中的所有文件注册适配器。您可以在要注册的包中添加package-info.java。

@XmlJavaTypeAdapters({
    @XmlJavaTypeAdapter(type=LocalDate.class, 
        value=LocalDateAdapter.class),
})
package PACKAGE_NAME;

import java.time.LocalDate;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;

适配器看起来像:

import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.time.LocalDate;

public class LocalDateAdapter extends XmlAdapter<String, LocalDate>{

    public LocalDate unmarshal(String v) throws Exception {
        return LocalDate.parse(v);
    }

    public String marshal(LocalDate v) throws Exception {
        return v.toString();
    }

}

答案 2 :(得分:0)

作为 Nikolay Antipov mentioned in this commment,已经有一个经过充分测试的 threetenprovides 14 type adapters(截至 2021-04-26)其中之一是:

LocalDateXmlAdapter

并且可以使用例如在某些 Java 领域是这样的(虽然我一般不推荐):

@XmlJavaTypeAdapter(value = LocalDateXmlAdapter.class) myLocalDt;

相反,我会推荐 package-info.java 方法在包级别的每个包中隐式执行此操作,以便它自动应用于例如所有包类中 LocalDate 类型的所有字段:

  • 创建一个名为 src/java/my/xmlconv/classes/package-info.java 的文件

  • 其内容:

    @XmlJavaTypeAdapters({
      @XmlJavaTypeAdapter(value=LocalDateTimeXmlAdapter.class, type=LocalDateTime.class)
    })
    package my.xmlconv.classes;
    
    import java.time.LocalDateTime;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
    import io.github.threetenjaxb.core.LocalDateTimeXmlAdapter;