为什么不将 Jackson 设置为接受空列表作为 Null 工作?

Why Doesn't Setting Jackson to Accept Empty Lists as Null Work?

我的公司有一个 Java Web 服务,使用 Spring Web,通过 REST API 接受 JSON。我们正在使用 Maven,我们的 Jackson 版本是 2.9。当我们的 API 不期望一个空列表时,我们试图防止当集成器传入一个空列表时抛出反序列化异常。

例如,这是我的应用程序 class:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@EnableWebMvc
@SpringBootApplication
public class ExampleApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(ExampleApplication.class, args);
    }
}

Student.java class:

import lombok.Data;
import java.util.Map;

@Data
public class Student {

    private String firstName;
    private String lastName;
    private Map<String, String> classGrades;
}

一个学生控制器:

package com.example.example.controllers;

import com.example.example.models.Student;
import org.springframework.http.RequestEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.stream.Stream;

@RestController()
@RequestMapping(value = "/Students/", produces = "application/json")
public class StudentController {

    @PostMapping(path = "")
    public RequestEntity<Student> createNewStudent(@RequestBody Student student) {

       return null;
    }
}

application.properties:

spring.jackson.deserialization.accept-empty-array-as-null-object=true

pom.xml 包含所有默认依赖项,并添加了以下内容:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.10</version>
</dependency>

每个其他项目文件默认为 Spring 初始化程序生成的项目结构。预期的请求正文(JSON 使用 Postman 形成):

{
  "firstName": "Mark",
  "lastName": "Twain",
  "classGrades": {

  }
}

工作正常。但是,如果任何字段(尽管在我们的特定情况下是 classGrades 字段)收到空列表,则会抛出 Jackson 反序列化异常。 JSON 请求失败的示例:

{
  "firstName": "Mark",
  "lastName": "Twain",
  "classGrades": []
}

以及抛出的异常:

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `java.util.LinkedHashMap` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.LinkedHashMap` out of START_ARRAY token
 at [Source: (PushbackInputStream); line: 65, column: 28] 

根据项目的 github 页面,选项 ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT 应该可以为我们解决这个问题。我们尝试直接在 ObjectMapper 配置对象上和 application.properties 内使用以下行进行设置:

spring.jackson.deserialization.accept-empty-array-as-null-object=true

这两种方法似乎都没有效果。我们目前正在使用 @JsonDeserialize(using = MyCustomDeserializer.class) annotaion 在容易出现此问题的字段上使用变通方法。但是,我们希望能够让我们所有的字段默认将空列表视为 null。

我们是否误解了配置选项并错误地使用了它?有没有一种方法可以在我们的应用程序中将空列表视为 null?如果可以,我们该如何实现?

地图序列化为

{ "k1": "v1", "k2": "v2"}

空 Map 序列化为

{ }

在您的示例中,您尝试将代表空列表或数组的 [] 放入 Map 中,这就是 Jackson 抱怨的原因。简单地说,不能将空列表映射到 Map 中。 这也解释了为什么启用 ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT 没有效果

更新

我错了。 Jackson 可以将空数组映射到 Map。 创建了一个最小的 springboot 示例,它使用 spring.jackson.deserialization.accept-empty-array-as-null-object=true 属性 并且可以将空数组 [] 映射到地图

如果需要,请勾选 here

对于这个示例,我的问题是 ExampleApplication class 中的 @EnableWebMvc 注释。删除该注释使我能够成功地将一个空数组发送到我的端点,然后端点将其作为空对象接收。

备注

我原来的问题仍然存在于我公司的应用程序中,即使在删除注释后也是如此。但是,这似乎是另一个可能与 ...accept-empty-arrays-as-null-object.

冲突的设置的问题