Search code examples
spring-bootkotlinenumsspring-restcontroller

How to deserialize WWW form field to enum in Spring?


I'm facing issue when trying deserialize input coming from WWW form to enum class in Spring application, in Kotlin.

My DTO and enum 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?)

Controller's POST request receiver method:

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

When I make POST request with status = 0 using Postman, request's failing with following exception.

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

When I make request with status = NORMAL then no exception, but that what I don't want. I'm using application/x-www-form-urlencoded content type in POST request. Please let me know where I'm doing wrong.


Solution

  • You may use Converter class for that. Note that request parameters my look like a numbers to you, but they are in fact strings. That's why converter below accepts String? and returns Status?. That means, it would be convenient for you if your enum accept it as well. Example: NORMAL("0"), ERROR("1").

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

    To make it work, converter must be registered as below.

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