使用 Jackson / Springboot 解析 Optional<T> 时出错

Error parsing Optional<T> with Jackson / Springboot

我有一个 class 并且更愿意使用值 Optional<T> 例如 Optional<Integer> value;.

在这个项目中 Springboot 用于创建网络控制器,客户端通过 json 发送/接收。

客户端put或者post时,解析java中的class有Optional<T>类型参数,失败;否则它工作正常。然而; Optional<T> 是首选,因为我们希望客户端能够在不使用字段时省略它们。

例如:

这个有效:

public class TestClass {

    private final int testValue;

    public TestClass(@JsonProperty("testValue") int testValue) {
        this.testValue = testValue;
    }

    public int getTestValue() {
        return testValue;
    }
}

这不是:

public class TestClass {

    private final Optional<Integer> testValue;

    public TestClass(@JsonProperty("testValue") Optional<Integer> testValue) {
        this.testValue = testValue;
    }

    public Optional<Integer> getTestValue() {
        return testValue;
    }
}

以下是来自 Gradle.

的一些版本行
springBootVersion = '1.5.8.RELEASE'

compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: '2.6.4'
compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jdk8', version: '2.6.3' 

当使用 Postman 进行 POST 且值为 int 时,一切正常。当我使用 Optional<Integer> 时,我从网络调用中收到以下错误响应。

总结:

"exception": "org.springframework.http.converter.HttpMessageNotReadableException", "message": "JSON parse error: 0; nested exception is com.fasterxml.jackson.databind.JsonMappingException: 0 (through reference chain: …(my class path)… [\"actions\"]->java.util.ArrayList[3])",

您需要将第二个示例更改为

public TestClass(@JsonProperty("testValue") int testValue) {
    this.testValue = Optional.of(testValue);
}

有一个 Jackson 模块可以帮助 serialize/deserialize Optional 参数。

<dependency>
   <groupId>com.fasterxml.jackson.datatype</groupId>
   <artifactId>jackson-datatype-jdk8</artifactId>
   <version>2.9.6</version>
</dependency>

然后使用您的 ObjectMapper:

注册模块
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module());

此处示例:https://www.baeldung.com/jackson-optional

java.util.Optional 不可序列化

可选意味着不一定有您要找的对象!所以你可以简单地使用一个包装器。您可以 return 对象(如果对象存在),或者如果您的对象不存在,您可以 return 404 状态。

public static <X> ResponseEntity<X> wrapOrNotFound(Optional<X> maybeResponse, HttpHeaders header) {
    return maybeResponse.map(response -> ResponseEntity.ok().headers(header).body(response))
            .orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}

在不更改任何现有代码的情况下将 Jackson 升级到版本 2.8.6 修复了它。

我确实按照上面的另一个答案,奇怪的是,升级到更高版本的'2.9.6'没有用。然而,它确实给了我一条新的错误消息,最终导致我进入一个线程,其他人也必须降级。