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

Posted

技术标签:

【中文标题】客户端发送的请求在语法上不正确 Java ZonedDateTime 后端【英文标题】:The request sent by the client was syntactically incorrect Java ZonedDateTime backend 【发布时间】:2019-02-20 23:43:32 【问题描述】:

我希望能在调试这个问题时得到一些帮助。 如果我将以下 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解析分区日期时间?

谢谢!

【问题讨论】:

请提供有关所使用的不同技术的更多信息 当然。你具体在找什么?假设 Spring MVC。我更感兴趣的是了解如何调试这个只是获得答案.. 不清楚你的ZonedDateTimeTypeConverter是如何实现的(请提供足够的信息),但一般ZonedDateTime不接受558851094.57158995之类的东西。尝试发送类似"2007-12-03T10:15:30+01:00[Europe/Paris]" 的字符串,如doc of ZonedDateTime @AlexKornhauser ,您使用哪个解析器,能否请您提供 Spring 配置部分?如果您不介意,请告诉我们您使用的 Spring 版本。 这不是一个 Swift 问题,这是一个 Java 问题。 【参考方案1】:

解决方案:

假设您使用的是最“默认”的配置,它基于FasterXML Jackson。

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


我创建了一个小型/最小示例,它基于 Spring 5.0.9Jackson 2.9.6(当前是最新版本)。

请在这里找到它:spring5-rest-zoneddatetime >>,主要部分是:

    EventDTO:

    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 层。

    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);
        
    
    
    

    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


附加信息:

    如果需要自定义序列化器/解串器,请查看this question >>

    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] 的秒数

    默认情况下,REST APi 响应将使用浮点数作为日期,例如在我们的例子中,响应看起来是这样的:

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

    要返回字符串值,请检查例如这个question >>

    还需要提及的是,如果您将使用 Spring Boot 代替(良好的入门) - 上面讨论的所有内容都可以开箱即用。

【讨论】:

对我来说,答案是我必须按照您的建议同时使用 Jackson 核心和 Datatypes,而不仅仅是一个。感谢您的明确答复!【参考方案2】:

以这种格式发送 2016-08-22T14:30+08:00[亚洲/吉隆坡]

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

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

【讨论】:

以上是关于客户端发送的请求在语法上不正确 Java ZonedDateTime 后端的主要内容,如果未能解决你的问题,请参考以下文章

Android 错误:MultipartEntity,客户端发送的请求在语法上不正确

验证表单“发送的请求在语法上不正确”时出现错误 400

input===》name属性异常错误

客户端发送的请求语法错误

在春季由resttemplate发出的每个请求发送客户端证书的正确方法是啥?

Nginx 限制ip的访问频率