Дезаминирование LocalDateTime с помощью модуля Jackson JSR310

Я использую библиотеку, описанную страницу Jackson Datatype JSR310, но мне все еще трудно заставить ее работать.

Я сконфигурировал следующий bean:

@Bean
@Primary
public ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JSR310Module());
    return mapper;
}

Когда я вызываю свой REST API, выходной формат даты равен yyyy-MM-dd'T'HH:ss.SSSSSS, например. 2015-04-11T00:10:38.905847. Это очень удобно обрабатывает мой код AngularJS.

Когда я хочу отправить что-то в REST API, дата отправляется как yyyy-MM-dd'T'HH:mm:ss.SSS'Z', например. 2015-04-09T08:30:00.000Z

Джексон продолжает жаловаться на "Z" в конце. Если я смотрю на LocalDateTimeDeserializer в документации, он использует DateTimeFormatter.ISO_LOCAL_DATE_TIME, который кипит до ISO_LOCAL_DATE'T'ISO_LOCAL_TIME, и он упоминает, что у него нет зоны переопределения.

Итак, я решил, что должен установить DateFormat в ObjectMapper, который я создаю:

@Bean
@Primary
public ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JSR310Module());
    mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
    return mapper;
}

Но это ничего не делает. Я изменил его на что-то простое, как yyyy-MM-dd, но сериализованная дата осталась в предыдущем формате, и десериализация тоже не затронута.

Что я делаю неправильно здесь, чтобы заставить это работать? Формат даты в моем JavaScript-коде, насколько я знаю, формат ISO 8601...

Ответ 1

Не нужно писать собственный сериализатор. Достаточно использовать значение по умолчанию, но создавая экземпляр с другим форматом (time_zone one), так что большая часть просто вырезается:

new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME)

В моем случае у меня есть contextResolver, как это для достижения на уровне конфигурации:

@Service 
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {  
    private final ObjectMapper mapper;

    public ObjectMapperContextResolver() {
        mapper = new ObjectMapper();
        JavaTimeModule javaTimeModule=new JavaTimeModule();
        // Hack time module to allow 'Z' at the end of string (i.e. javascript json's) 
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME));
        mapper.registerModule(javaTimeModule);
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    }

    @Override
    public ObjectMapper getContext(Class<?> type) {
        return mapper;
    }  
}

Ответ 2

На данный момент LocalDateTimeDeserializer, похоже, не уважает формат даты, установленный для объекта mapper.

Чтобы сделать это, вы можете переопределить LocalDateTimeDeserializer или переключиться на использование ZoneDateTime, который обрабатывает "Z" char в конце.

Вот пример:

public class Java8DateFormat {
    public static void main(String[] args) throws IOException {
        final ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JSR310Module());
        // mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));

        final String date = mapper.writeValueAsString(new Date());
        System.out.println(date);
        System.out.println(mapper.readValue(date, ZonedDateTime.class));
    }
}

Вывод:

"2015-04-11T18:24:47.815Z"
2015-04-11T18:24:47.815Z[GMT]

Ответ 3

Спящий режим 4, Spring 4 - REST WS, Клиент - Spring Загрузка 1.5.2. В моем случае я использовал в классе Entity ZonedDateTime для сопоставления Timestamp в базе данных. Спящий режим, а также Spring Boot REST отлично работают. Я должен добавлять библиотеки только в файл pom:

    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>${jackson.version}</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jsr310 -->
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
        <version>${jackson.version}</version>
    </dependency>

Итак, я полагаю, что этот конвертер реализован внутри Spring для LocalDateTime. The jackson.version является последним.