spring-bootrestkotlinstrong-typinghttp-request-parameters

Typing does not work when creating a map in Kotlin through spring boot @RequestParam


I am using spring boot and have made the following controller where I explicitly specify key and value types.

@PostMapping("DAC/set")
    fun setDac(@RequestParam map: HashMap<Int, Float>): ResponseEntity<JSONObject> {
        println(map)
        return dac()
    }

When I send a request like this:

http://localhost:9090/adam6024/DAC/set?a=abc,b=d,d=v

I am getting this output in console:

{a=abc,b=d,d=v}

Why am I not getting an error? Moreover, I cannot add string values to the map, my IDE does not allow me.


Solution

  • I'm not 100% sure, but my guess would be, that this is because of generic type erasure.

    Basically, the types defined as part of the generic do not exist any longer during runtime. When Spring reads the request params and puts them into the HashMap, the types are no longer known, thus no error is thrown. During runtime the type of the generic is basically HashMap<Object, Object> (Java) / HashMap<Any?, Any?> (Kotlin).

    According to the documentation, @RequestParam may return either Map<String, String> or MultiValueMap<String, String>, when no parameter name is provided.

    Thus, you most likely should declare your @RequestParam as Map<String, String> and do any required type conversions yourself.

    @PostMapping("DAC/set")
    fun setDac(@RequestParam map: Map<String, String>): ResponseEntity<JSONObject> {
        val typedMap = map.entries
            .associate { (key, value) -> key.toInt() to value.toFloat() }
       
        return dac()
    }
    

    If you know the parameter name upfront, you may inject them separately instead, in which case Spring does the type conversion for you.

    @PostMapping("DAC/set")
    fun setDac(@RequestParam(name = "1") first: Float, @RequestParam(name = "2") second: Float): ResponseEntity<JSONObject> {
       // ...
       
       return dac()
    }