客户端发送的请求在语法上不正确 Java ZonedDateTime 后端

The request sent by the client was syntactically incorrect 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 字符串格式 ZonedDateTime 自动接受的时间或 (2) 如何制作 DTO 来解析分区日期时间?

谢谢!

解决方案:

假设您使用最多的 "default" 配置,它基于 FasterXML Jackson.

如果是这样,那么您只需要在您的应用程序中为 ZonedDateTime 配置正确的序列化器和解串器;它可能是自定义的,也可能是来自 jackson-datatype-jsr310 (推荐).


我创建了一个 small/minimal 示例,它基于 Spring 5.0.9Jackson 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 getter 和 setter.

    注意: 我在这里忽略 @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.ZonedDateTimeSerializercom.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.


附加信息:

  1. 如需自定义serializer/desirializer,请勾选

  2. time 字段将支持下一个日期格式:

    • "2018-01-01T22:25:15+01:00[Europe/Paris]" - 不完全是 ISO 8601 btw
    • "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
    }
    

    改为return字符串值,请检查例如这个

  4. 还需要提到的是,如果您将使用 Spring Boot 代替(好的启动器)- 上面讨论的所有事情都可以解决盒子.

以这种格式发送 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"));