I have the following controller method:
@RequestMapping(value=\"/map/update\", method=RequestMethod.POST, produces = \"application/json; charset=utf-8\")
@Re
(this answer is in Kotlin, for Java see https://stackoverflow.com/a/64061936)
For those using kotlin and jackson, here is the ValidatedList class that do not require wrapping, that is, it will still be serialized/deserialized as a usual list:
class ValidatedList {
/**
* By default, spring-boot cannot validate lists, as they are generic AND do not conform to the Java Bean definition.
* This is one work-around: create a wrapper that fits the Java Bean definition, and use Jackson annotations to
* make the wrapper disappear upon (de)serialization.
* Do not change anything (such as making the _value field private) or it won't work anymore !
*
* Usage:
* ```
* @PostMapping("/something")
* fun someRestControllerMethod(@Valid @RequestBody pojoList: ValidatedList){
* // access list with:
* pojoList.values
*}
* ```
*/
@JsonValue
@Valid
@NotNull
@Size(min = 1, message = "array body must contain at least one item.")
var _values: List? = null
val values: List
get() = _values!!
@JsonCreator
constructor(vararg list: E) {
this._values = list.asList()
}
}
Advantages:
@Validated annotation@Size)400 Bad Request (which is not the case when using javax and @Validated annotation)Example:
data class N(
@field:Min(value = 0, message = "id must be positive.")
val id: Long? = null,
@field:NotNull
@field:Size(min = 2, max = 32, message = "wrong size: should be 32 chars long.")
val token: String? = null
)
@RestController
class XController {
@PostMapping("/ns")
fun getNs(@Valid @NotNull @RequestBody wrap: ListWrapper) = wrap
}
Submit ok:
curl -H "Content-Type: application/json" -X POST http://localhost:8080/ns -d '[{"id": 11, "token": "something"}]'
[{"id" : 11, "token" : "something"}]
Submit empty body:
curl -H "Content-Type: application/json" -X POST http://localhost:8080/ns -d '[]'
{
"timestamp" : "2020-09-25T08:49:30.324+00:00",
"message" : "Validation failed for object='listWrapper'. Error count: 1",
"error" : "Bad Request",
"path" : "/ns",
"status" : 400,
"exception" : "org.springframework.web.bind.MethodArgumentNotValidException",
"trace":"org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public com.example.demo.test.XController$ListWrapper com.example.demo.test.XController.getNs(com.example.demo.test.XController$ListWrapper): [Field error in object 'listWrapper' on field '_values': rejected value [[]]; codes [Size.listWrapper._values,Size._values,Size.java.util.List,Size]; [...]"
}
Submit invalid items:
curl -H "Content-Type: application/json" -X POST http://localhost:8080/ns -d '[{"id": -11, "token": ""}]'
{
"message" : "Validation failed for object='listWrapper'. Error count: 2",
"path" : "/ns",
"exception" : "org.springframework.web.bind.MethodArgumentNotValidException",
"timestamp" : "2020-09-25T08:49:54.505+00:00",
"error" : "Bad Request",
"status" : 400,
"trace":"org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public com.example.demo.test.XController$ListWrapper com.example.demo.test.XController.getNs(com.example.demo.test.XController$ListWrapper) with 2 errors: [...]"
}