Запрос, отправленный клиентом, был синтаксически неверным бэкэндом Java ZonedDateTime - PullRequest
0 голосов
/ 17 сентября 2018

Я надеюсь получить помощь в устранении этой проблемы.Если я отправлю следующий 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 ZonedDateTime автоматически принимает, или (2) как сделать DTO для разбора зонированной даты?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

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

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

ZonedDateTime klDateTime = ldt.atZone(ZoneId.of("Asia/Kuala_Lumpur"));
0 голосов
/ 24 сентября 2018

Решение:

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

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


Я создал небольшой / минимальный пример, основанный на Spring 5.0.9 и Jackson 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. Если потребуется специальный сериализатор / десиализатор, проверьте этот вопрос >>

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

    • "2018-01-01T22:25:15+01:00[Europe/Paris]" - не полностью ISO 8601 кстати
    • "2018-01-01T22:25:15+01:00"
    • "2018-01-01T22:25:15.000000001Z"
    • 1514768461.000000001 - число с плавающей точкой, количество секунд от 1970-01-01, 00:00:00 [UTC]
  3. По умолчанию в ответе REST APi для дат используются числа с плавающей точкой, например, в нашем случае ответ будет выглядеть так:

    {
        "id": 3,
        "name": "Test event",
        "time": 1514768460
    }
    

    Чтобы вместо этого возвращать строковые значения, проверьте, например, это вопрос >>

  4. Также необходимо отметить, что если вы будете использовать Spring Boot вместо (хороший стартер) - все, что обсуждалось выше, будет работать из коробки.

...