Làm thế nào để bạn chỉ định định dạng ngày được sử dụng khi JAXB thống nhất xsd: dateTime?


86

Khi JAXB sắp xếp một đối tượng date ( XMLGregorianCalendar) thành một phần tử xsd: dateTime. Làm thế nào bạn có thể chỉ định định dạng của XML kết quả?

Ví dụ: Định dạng dữ liệu mặc định sử dụng mili giây, <StartDate>2012-08-21T13:21:58.000Z</StartDate> tôi cần bỏ qua mili giây. <StartDate>2012-08-21T13:21:58Z</StartDate>

Làm cách nào để chỉ định dạng đầu ra / định dạng ngày tháng mà tôi muốn nó sử dụng? Tôi đang sử dụng javax.xml.datatype.DatatypeFactoryđể tạo XMLGregorianCalendarđối tượng.

XMLGregorianCalendar xmlCal = datatypeFactory.newXMLGregorianCalendar(cal);

Câu trả lời:


126

Bạn có thể sử dụng một XmlAdapterđể tùy chỉnh cách một loại ngày tháng được ghi vào XML.

package com.example;

import java.text.SimpleDateFormat;
import java.util.Date;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class DateAdapter extends XmlAdapter<String, Date> {

    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

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

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

}

Sau đó, bạn sử dụng @XmlJavaTypeAdapterchú thích để chỉ định rằng XmlAdapternên được sử dụng cho một trường / thuộc tính cụ thể.

@XmlElement(name = "timestamp", required = true) 
@XmlJavaTypeAdapter(DateAdapter.class)
protected Date timestamp; 

Sử dụng tệp ràng buộc xjb:

<xjc:javaType name="java.util.Date" xmlType="xs:dateTime"
        adapter="com.example.DateAdapter"/>

sẽ tạo ra chú thích được đề cập ở trên.
(Cuối cùng bằng cách thêm xjckhông gian tên xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc":)


2
Cảm ơn câu trả lời này! Có thể thêm chú thích qua xsd hoặc tệp ràng buộc không? Tôi chỉ tìm thấy mục blog được trích dẫn thường xuyên của bạn về binds.xml, nhưng điều này bao gồm các khía cạnh khác, tôi nghĩ.
touristda

9
Như @PeterRader đã đề cập, SimpleDateFormat không an toàn cho luồng - nếu hai luồng nhập vào đồng thời cả nguyên soái hoặc không quản lý đồng thời, bạn có thể nhận được kết quả rất khó lường. Điều này sẽ rất khó để tái tạo trong thử nghiệm thông thường, nhưng có thể xảy ra dưới tải và sẽ cực kỳ khó chẩn đoán. Tốt hơn là tạo một SimpleDateFormat mới với nguyên soái và nguyên soái (nhưng sử dụng chuỗi định dạng tĩnh nếu cần).
Colselaw

1
Tôi đã làm điều này và nó gần như hoạt động. Tuy nhiên, tôi đã gặp Class has two properties of the same name "timeSeries"lỗi - điều này đã được giải quyết bằng cách đặt chú thích ở getter chứ không phải ở cấp thành viên. (Nhờ @megathor từ stackoverflow.com/questions/6768544/... )
gordon613

1
@ gordon613 - Bài viết này sẽ cung cấp thêm một số thông tin về nơi để đặt chú thích: blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
bdoughan

3
Vì khối quan trọng được bảo vệ bằng "đồng bộ hóa" nên không có bất kỳ vấn đề nào. Sẽ có vấn đề (hiệu suất) nếu nhiều cuộc gọi được thực hiện.
Mike Argyriou

17

Tôi sử dụng SimpleDateFormat để tạo XMLGregorianCalendar, chẳng hạn như trong ví dụ sau:

public static XMLGregorianCalendar getXmlDate(Date date) throws DatatypeConfigurationException {
    return DatatypeFactory.newInstance().newXMLGregorianCalendar(new SimpleDateFormat("yyyy-MM-dd").format(date));
}

public static XMLGregorianCalendar getXmlDateTime(Date date) throws DatatypeConfigurationException {
    return DatatypeFactory.newInstance().newXMLGregorianCalendar(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(date));
}

Phương pháp đầu tiên tạo một bản sao của XMLGregorianCalendar được định dạng bởi trình điều phối XML dưới dạng xsd: date hợp lệ, phương pháp thứ hai dẫn đến một xsd: dateTime hợp lệ.


2

Cách rất dễ dàng với tôi. Định dạng XMLGregorianCalendar để sắp xếp trong java.

Tôi chỉ tạo dữ liệu của mình ở định dạng tốt. Ý toStringchí được gọi là tạo ra kết quả tốt.

public static final XMLGregorianCalendar getDate(Date d) {
    try {
        return DatatypeFactory.newInstance().newXMLGregorianCalendar(new SimpleDateFormat("yyyy-MM-dd").format(d));
    } catch (DatatypeConfigurationException e) {
        return null;
    }
}

1

https://www.baeldung.com/jaxb

public class DateAdapter extends XmlAdapter<String, Date> {

    private static final ThreadLocal<DateFormat> dateFormat 
      = new ThreadLocal<DateFormat>() {

        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    }

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

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

0

Sử dụng:

import com.company.LocalDateAdapter.yyyyMMdd;
...

@XmlElement(name = "PROC-DATE")
@XmlJavaTypeAdapter(yyyyMMdd.class)
private LocalDate processingDate;

LocalDateAdapter

import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class LocalDateAdapter extends XmlAdapter<String, LocalDate> {

    public static final class yyyyMMdd extends LocalDateAdapter {
        public yyyyMMdd() {
            super("yyyyMMdd");
        }
    }

    public static final class yyyy_MM_dd extends LocalDateAdapter {
        public yyyy_MM_dd() {
            super("yyyy-MM-dd");
        }
    }

    private final DateTimeFormatter formatter;

    public LocalDateAdapter(String pattern) {
        formatter = DateTimeFormat.forPattern(pattern);
    }

    @Override
    public String marshal(LocalDate date) throws Exception {
        return formatter.print(date);
    }

    @Override
    public LocalDate unmarshal(String date) throws Exception {
        return formatter.parseLocalDate(date);
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.