如何反序列化 WWW 表单字段以在 Spring 中枚举?

How to deserialize WWW form field to enum in Spring?

我在 Kotlin 中尝试反序列化来自 WWW 表单的输入以枚举 Spring 应用程序中的 class 时遇到问题。

我的 DTO 和枚举 classes:

enum class Status(@get:JsonValue val value: Int) {
    NORMAL(0),
    ERROR(1);

    companion object {
        @JvmStatic
        @JsonCreator
        fun of(number: Int?): Status? {
            return values().find { it.value == number }
        }
    }
}

data class RequestData(val status: Status?)

控制器的 POST 请求接收器方法:

@PostMapping("/post")
fun register(@Valid data: RequestData, error: Errors) {}

当我使用 Postman 通过 status = 0 发出 POST 请求时,请求失败并出现以下异常。

java.lang.IllegalArgumentException: Parameter specified as non-null is null: method com.example.Controller.post, parameter data

当我用 status = NORMAL 提出请求时,也不例外,但那是我不想要的。 我在 POST 请求中使用 application/x-www-form-urlencoded 内容类型。 请告诉我哪里做错了。

你就用这个名字吧。

ex) 状态 = 正常

value 重要吗?您可以使用序数

enum class Status{
    NORMAL,
    ERROR,
}

println(NORMAL.ordinal)
//result:0

这是个玩笑,但如果你需要

enum class Status(val value:String){
    `0`("NORMAL"),`1`("ERROR")
}

println(data.status.value)

您可以为此使用 Converter class。请注意,请求参数我看起来像一个数字,但它们实际上是字符串。这就是下面的转换器接受 String? 和 returns Status? 的原因。这意味着,如果您的 enum 也接受它,对您来说会很方便。示例:NORMAL("0"), ERROR("1").

class ConvStringToStatus : Converter<String?, Status?> {
    override fun convert(source: String?) = Status.of(source)
}

要使其正常工作,转换器必须如下注册。

@Configuration
class WebConfig : WebMvcConfigurer {
    override fun addFormatters(registry: FormatterRegistry) {
        registry.addConverter(ConvStringToStatus())
    }
}

对于仍在寻找和找到它的任何人。如果您添加 jackson-module-kotlin 依赖项,示例代码可以工作并且不会抛出 non-null field is null 异常。它应该与您的 com.fasterxml.jackson.core 版本

匹配
<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-kotlin</artifactId>
    <version>2.9.8</version>
</dependency>