Запрос, отправленный клиентом, был синтаксически некорректным Java ZonedDateTime backend

Я надеюсь получить некоторую помощь в отладке этой проблемы. Если я отправлю следующий JSON на мой сервер, он работает правильно:

{
    "approvalRequired": false,
    "location": {
        "locationName": "<+37.33233141,-122.03121860> +/- 5.00m (speed 0.00 mps / course -1.00) @ 9/16/18, 9:24:59 PM Pacific Daylight Time",
        "longitude": -122.0312186,
        "latitude": 37.332331410000002
    }
}

однако, если я сейчас отправлю следующее:

{
    "approvalRequired": false,
    "scheduledStartTime": "2016-01-01T10:24:00+01:00",
    "location": {
        "locationName": "<+37.33233141,-122.03121860> +/- 5.00m (speed 0.00 mps / course -1.00) @ 9/16/18, 9:24:59 PM Pacific Daylight Time",
        "longitude": -122.0312186,
        "latitude": 37.332331410000002
    }
}

Я получаю вышеуказанную ошибку. В моем бэкэнд-коде у меня есть следующее:

@DynamoDBTypeConverted(converter = ZonedDateTimeTypeConverter.class)
@DynamoDBAttribute(attributeName = "scheduledStartTime")
public ZonedDateTime scheduledStartTime;

и подпись метода API выглядит следующим образом:

@RequestMapping(method = RequestMethod.POST)
public ResponseEntity create(@RequestBody Event event) {...}

Я считаю, что проблема в том, что JSON не может быть проанализирован в ZonedDateTime. У кого-нибудь есть совет, как либо (1) какое время JSON string format ZonedDateTime автоматически принимает или (2) Как сделать DTO для разбора зонированного времени даты?

спасибо!

2 ответов


устранение:

Предположим, вы используете самую" стандартную " конфигурацию, которая основана на FasterXML Jackson.

если да, то вам просто нужно правильно настроить сериализатор и desirializer для ZonedDateTime в вашем приложении; и это могут быть либо пользовательские, либо из Джексон-тип данных-jsr310 (рекомендуется).


я создал небольшой/минимальный пример, который основан на Весна 5.0.9 и Джексон 2.9.6 (последние версии в настоящее время).

пожалуйста, найдите его здесь:spring5-rest-zoneddatetime >>, основные части:

  1. Event DTO:

    public class Event {
    
        private long id;
        private String name;
        private ZonedDateTime time;
    
        // Constructors, public getters and setters
    
    }
    

    поле time может быть public одно такое же к вашему образцу, оно также отлично, но если поле private - тогда вам понадобится public геттер и сеттер.

    Примечание: я игнорирую здесь @DynamoDBTypeConverted и @DynamoDBAttribute аннотации, поскольку они связаны с логикой сохранения, а не с уровнем REST.

  2. EventController содержит только один метод, одинаковый для вашего:

    @RestController
    public class EventController {
    
        @RequestMapping(value = "/event", method = RequestMethod.POST)
        public ResponseEntity post(@RequestBody Event event) {
            System.out.println("Event posted: " + event.toString());
            return ResponseEntity.ok(event);
        }
    
    }
    
  3. зависимостей в pom.xml выглядит так:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.0.9.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.6</version>
    </dependency>
    
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
        <version>2.9.6</version>
    </dependency>
    

    важным здесь является JSR-310 реализация типа данных, которая также вводит com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer и com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.


дополнительные информация:

  1. в случае необходимости пользовательского сериализатора / desirializer, пожалуйста, проверьте этот вопрос >>

  2. следующие форматы даты будут поддерживаться для


отправить в этом формате 2016-08-22T14:30+08:00[Азия/Kuala_Lumpur]

LocalDateTime ldt = LocalDateTime.of(2016, Month.AUGUST, 22, 14, 30);

ZonedDateTime klDateTime = ldt.atZone(ZoneId.of("Asia/Kuala_Lumpur"));