【问题标题】:How to change programmatically the default JAXB date serialization?如何以编程方式更改默认的 JAXB 日期序列化?
【发布时间】:2011-06-16 20:32:11
【问题描述】:

有没有办法改变默认方式 jaxb 序列化/反序列化类型,在我的情况下是日期,而不通过注释和/或通过这里提到的 xml jaxb 绑定指定它 http://jaxb.java.net/guide/Using_different_datatypes.html

我基本上想做这样的事情:

    JAXBContext jaxbContext = ...;
    Marshaller marshaller = jaxbContext.createMarshaller().setAdapter(new DateAdapter(dateFormat));

拥有一个以自定义方式序列化/反序列化日期的预配置 JaxBContext 或 Marshaller/Unmarshaller..

找不到任何显示如何通过注解或静态使用 xml 绑定文件的资源。 谢谢!

【问题讨论】:

  • javax.xml.bind.Marshaller.setAdapter(XmlAdapter) 不适合你吗?
  • @lexicore - javax.xml.bind.Marshaller.setAdapter(XmlAdapter) 用于在模型已配置为使用 XmlAdapter 而不引入 XmlAdapter 时传入初始化的 XmlAdapter。示例见:stackoverflow.com/questions/5319024/…
  • @XmlJavaTypeAdapter(s) 注释是不可避免的,这对框架来说是一个很大的痛苦。对于 XStream,我们可以注册一个转换器以应用于所有 Foo 字段,但对于 jaxb 我们不能,因为它希望我们更改用户的域 package-info.java 文件...

标签: java xml jaxb


【解决方案1】:

这并不完全是您正在寻找的内容,但它胜过单独注释每个日期字段。您可以在包级别设置 XmlJavaTypeAdapter,以便包中对 Date 的每个引用都将使用它。如果你的对象在 com.example 包中,你应该添加一个 package-info.java 文件,内容如下:

@XmlJavaTypeAdapter(value=MyCustomDateAdapter.class,type=Date.class)
package com.example;

【讨论】:

  • +1 - 相关示例参见:bdoughan.blogspot.com/2011/05/…
  • 这是否也会处理 com.example 的子包,例如 com.example.foo 和 com.example.bar?
  • 这不是程序化的:它不适用于框架:(
【解决方案2】:

试试这个:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement(name = "event")
public class Event {

    private Date date;
    private String description;

    @XmlJavaTypeAdapter(DateFormatterAdapter.class)
    public Date getDate() {
        return date;
    }

    public void setDate(final Date date) {
        this.date = date;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(final String description) {
        this.description = description;
    }

    private static class DateFormatterAdapter extends XmlAdapter<String, Date> {
        private final SimpleDateFormat dateFormat = new SimpleDateFormat("dd_mm_yyyy");

        @Override
        public Date unmarshal(final String v) throws Exception {
            return dateFormat.parse(v);
        }

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

    public static void main(final String[] args) throws Exception {
        final JAXBContext context = JAXBContext.newInstance(Event.class);
        final Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        final Event event = new Event();
        event.setDate(new Date());
        event.setDescription("im rick james");

        marshaller.marshal(event, System.out);
    }
}

这会产生:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<event>
    <date>16_05_2011</date>
    <description>im rick james</description>
</event>

【讨论】:

  • 这不是我要找的,您的 Event 对象已经有一个注释,指定如何序列化日期 (@XmlJavaTypeAdapter)。我需要的是一个预先配置的 jaxb (un) marshaller,它已经知道如何(反)序列化某些类型,而无需预先注释传递给它的对象..
  • 请注意,SimpleDateFormat "dd_mm_yyyy" 将显示天、分和年。可能“dd_MM_yyyy”是更好的选择。
  • 是否可以通过验证来做marshal?
【解决方案3】:

在搜索了整个 jaxb 文档和许多教程之后,除了我们在 XMLAdapter 中硬编码的内容之外,我没有找到任何可以配置日期的答案。 我将一个属性文件放在具有日期格式的类路径中,例如: dateFormat=mm-dd-YYYY

现在你的 XMLAdapter 实现如下:

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class ConfigurableAdapterForDate extends XmlAdapter<String, Date>{

    private static final String FORMAT = "yyyy-mm-dd";
    private String formatFromFile =  null;
    private SimpleDateFormat format = new SimpleDateFormat();

    private void setFormatFromFile() throws IOException {
        //load property file
        Properties prop = new Properties();
        InputStream is = this.getClass().getResourceAsStream("<path to your property file>");
        prop.load(is);

        //get the format from loaded property file
        formatFromFile = prop.getPropertyValue("dateFormat");

        if(formatFromFile != null) {
            format.applyPattern(formatFromFile);
        }
        else {
            format.applyPattern(FORMAT );
        }
    }

    @Override
    public Date unmarshal(String v) throws Exception {
        this.setFormatFromFile();
        return format.parse(v);
    }

    @Override
    public String marshal(Date v) throws Exception {
        this.setFormatFromFile();
        return format.format(v);
    }

}

现在您可以将@XmlJavaTypeAdapter(ConfigurableAdapterForDate.class) 用于您想要序列化/反序列化的日期对象。 一个是免费使用spring也加载属性文件。以上代码将相应地配置您的日期。

【讨论】:

  • 属性的验证将失败,因为它被声明为字符串,如下所示 [导出日期 ].
猜你喜欢
  • 2013-09-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 2023-03-28
  • 2014-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多