Рубрики
Без рубрики

Даты unmarshalling с использованием JAXB

JAXB имеет базовую поддержку для чтения форматов данных, встроенных в. Давайте расширим эту функциональность для поддержки нетрадиционных форматов и типов Java 8 Date/Time.

Автор оригинала: Catalin Burcea.

1. Введение

В этом учебнике мы увидим, как разграничить объекты даты с различными форматами с помощью JAXB .

Во-первых, мы покроем формат даты по умолчанию. Затем мы изумим, как использовать различные форматы. Мы также увидим, как мы можем справиться с общей проблемой, которая возникает с этими методами.

2. Схема привязки Java

Во-первых, нам необходимо понять взаимосвязь между типами XML Schema и Java- . В частности, мы заинтересованы в отображении между объектами XML Schema и Java-дата.

Согласно Схема для отображения java , Есть три типа данных Schema, которые мы должны принять во внимание: xsd:дата , xsd:время и xsd:dateTime . Как мы видим, все они нанесены на карту Javax.xml.datatype.XMLGregorianCalendar .

Мы также должны понять форматы по умолчанию для этих типов XML Schema. xsd:дата и xsd:время типы данных имеют ” YYYY-MM-DD” и ” hh:mm:ss” Форматы. xsd:dateTime формат “ YYYY-MM-DDThh:mm:ss” где ” T” является сепаратором, указывающим начало раздела времени.

3. Использование формата даты шемы по умолчанию

Мы собираемся создать пример, который разграничит объекты даты. Давайте сосредоточимся на xsd:dateTime тип данных, потому что это суперсет других типов.

Давайте использовать простой файл XML, который описывает книгу:


    Book1
    1979-10-21T03:31:12

Мы хотим сопоставить файл с соответствующими Java- Книжный объект:

@XmlRootElement(name = "book")
public class Book {

    @XmlElement(name = "title", required = true)
    private String title;

    @XmlElement(name = "published", required = true)
    private XMLGregorianCalendar published;

    @Override
    public String toString() {
        return "[title: " + title + "; published: " + published.toString() + "]";
    }

}

Наконец, нам необходимо создать клиентское приложение, которое преобразует данные XML в java-объекты, полученные jaxB:

public static Book unmarshalDates(InputStream inputFile) 
  throws JAXBException {
    JAXBContext jaxbContext = JAXBContext.newInstance(Book.class);
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
    return (Book) jaxbUnmarshaller.unmarshal(inputFile);
}

В вышеуказаном коде мы определили JAXBContext которая является точкой входа в API JAXB. Затем мы использовали JAXB- Унмаршаллер на входной поток для того, чтобы прочитать наш объект:

Если мы забудем вышеуказанный код и напечатаем результат, мы получим следующее Книжный объект:

[title: Book1; published: 1979-11-28T02:31:32]

Следует отметить, что, несмотря на то, что отображение по умолчанию для xsd:dateTime является XMLGregorianCalendar , мы могли бы также использовать более распространенные типы Java: java.util.Date и java.util.Calendar , в соответствии с Руководство для пользователей JAXB .

4. Использование пользовательского формата даты

Приведенный выше пример работает, потому что мы используем формат даты схемы по умолчанию, “YYYY-MM-DDThh:mm:ss”.

Но что, если мы хотим использовать другой формат, как “YYYY-MM-DD hh:mm:ss”, избавиться от “Т” разделитель? Если мы заменим делимитр космическим символом в нашем файле XML, то unmarshalling по умолчанию потерпит неудачу.

4.1. Строительство пользовательского XmlAdapter

Для того, чтобы использовать другой формат даты, мы должны определить XmlАдаптер .

Давайте также посмотрим, как сопоставить xsd:dateTime введать в java.util.Date объект с нашим пользовательским XmlАдаптер:

public class DateAdapter extends XmlAdapter {

    private static final String CUSTOM_FORMAT_STRING = "yyyy-MM-dd HH:mm:ss";

    @Override
    public String marshal(Date v) {
        return new SimpleDateFormat(CUSTOM_FORMAT_STRING).format(v);
    }

    @Override
    public Date unmarshal(String v) throws ParseException {
        return new SimpleDateFormat(CUSTOM_FORMAT_STRING).parse(v);
    }

}

В этом адаптере мы использовали ПростойdateФормат чтобы отформатировать нашу дату. Мы должны быть осторожны, как ПростойdateФормат не поток-безопасный . Чтобы избежать проблем с несколькими потоками с общим ПростойdateФормат объект, мы создаем новый каждый раз, когда мы в ней нуждается.

4.2. Внутренние данные XmlAdapter

Как видим, XmlAdapter имеет два параметра типа , в данном случае, Струнные и Дата . Первый тип используется внутри XML и называется типом значения. В этом случае JAXB знает, как преобразовать значение XML в Струнные . Второй называется связанным типом и относится к значению в нашем Java-объекте.

Цель адаптера состоит в том, чтобы преобразовать между типом значения и связанным типом, таким образом, что JAXB не может сделать по умолчанию.

Для того, чтобы построить пользовательский Xml Адаптер , мы должны переопределить два метода: XmlAdapter.marshal() и XmlAdapter.unmarshal() .

Во время unmarshalling обязательная структура JAXB сначала анмаршала представление XML на Струнные а затем вызывает DateAdapter.unmarshal() адаптировать тип значения к Дата . Во время маршаллинга обязательная структура JAXB вызывает ДатаАдаптер.маршал () адаптировать Дата Струнные , который затем marshaled к представлению XML.

4.3. Интеграция через аннотации JAXB

ДатаАдаптер работает как плагин для JAXB, и мы собираемся прикрепить его к нашей дате поле с помощью @XmlJavaTypeAdapter аннотация. @XmlJavaTypeAdapte r аннотация определяет использование XmlAdapter для пользовательских unmarshalling :

@XmlRootElement(name = "book")
public class BookDateAdapter {

    // same as before

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

    // same as before

}

Мы также используем стандартные аннотации JAXB : @XmlRootElement и @XmlElement Аннотации.

Наконец, давайте забудем новый код:

[title: Book1; published: Wed Nov 28 02:31:32 EET 1979]

5. Даты unmarshalling в Java 8

Java 8 представила новую Дата/время API . Здесь мы сосредоточимся на Местное время класс, который является одним из наиболее часто используемых.

5.1. Строительство локальногоdateTime на основе XmlAdapter

По умолчанию JAXB не может автоматически связывать xsd:dateTime значение для Местное время объекта независимо от формата даты. Для преобразования значения даты XML Schema в или из Местное время объект, мы должны определить другую XmlAdapter похож на предыдущий:

public class LocalDateTimeAdapter extends XmlAdapter {

    private DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public String marshal(LocalDateTime dateTime) {
        return dateTime.format(dateFormat);
    }

    @Override
    public LocalDateTime unmarshal(String dateTime) {
        return LocalDateTime.parse(dateTime, dateFormat);
    }

}

В этом случае мы использовали ДатаTimeФорматер вместо ПростойdateФормат . Первый был представлен на Java 8 и совместим с новым Дата/время API.

Обратите внимание, что операции преобразования могут делиться ДатаTimeФорматер объект, потому ДатаTimeФорматер является поток-безопасной.

5.2. Интеграция нового адаптера

Теперь давайте заменим старый адаптер на новый в нашем Книжный класса, а также Дата с Местное время :

@XmlRootElement(name = "book")
public class BookLocalDateTimeAdapter {

    // same as before

    @XmlElement(name = "published", required = true)
    @XmlJavaTypeAdapter(LocalDateTimeAdapter.class)
    private LocalDateTime published;

    // same as before

}

Если мы забудем вышеуказанный код, мы получим выход:

[title: Book1; published: 1979-11-28T02:31:32]

Обратите внимание, что LocalDateTime.toString () добавляет “Т” делимитер между датой и временем.

6. Заключение

В этом учебнике мы исследовали даты unmarshalling с использованием JAXB .

Во-первых, мы рассмотрели карту типа XML Schema to Java и создали пример с использованием формата даты XML Schema по умолчанию.

Затем мы узнали, как использовать пользовательский формат даты на основе пользовательского XmlAdapter и увидел, как справиться с безопасностью потока ПростойdateФормат .

Наконец, мы использовали превосходный, безопасный для потоков API Java 8 Date/Time и неустойкие даты с пользовательскими форматами.

Как всегда, исходный код, используемый в учебнике, доступен более на GitHub .