I ran into this same problem these days and maybe some more detail might be helpful to somebody else.
I was looking some security guidelines for REST APIs and crossed a very intriguing issue with json arrays. Check the link for details, but basically, you should wrap them within an Object as we already saw in this post question.
So, instead of:
[
{
"name": "order1"
},
{
"name": "order2"
}
]
It's advisable that we always do:
{
"data": [
{
"name": "order1"
},
{
"name": "order2"
}
]
}
This is pretty straight-forward when you doing a GET, but might give you some trouble if, instead, your trying to POST/PUT the very same json.
In my case, I had more than one GET that was a List and more than one POST/PUT that would receive the very same json.
So what I end up doing was to use a very simple Wrapper object for a List:
public class Wrapper<T> {
private List<T> data;
public Wrapper() {}
public Wrapper(List<T> data) {
this.data = data;
}
public List<T> getData() {
return data;
}
public void setData(List<T> data) {
this.data = data;
}
}
Serialization of my lists were made with a @ControllerAdvice:
@ControllerAdvice
public class JSONResponseWrapper implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
@SuppressWarnings("unchecked")
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (body instanceof List) {
return new Wrapper<>((List<Object>) body);
}
else if (body instanceof Map) {
return Collections.singletonMap("data", body);
}
return body;
}
}
So, all the Lists and Maps where wrapped over a data object as below:
{
"data": [
{...}
]
}
Deserialization was still default, just using de Wrapper Object:
@PostMapping("/resource")
public ResponseEntity<Void> setResources(@RequestBody Wrapper<ResourceDTO> wrappedResources) {
List<ResourceDTO> resources = wrappedResources.getData();
// your code here
return ResponseEntity
.ok()
.build();
}
That was it! Hope it helps someone.
Note: tested with SpringBoot 1.5.5.RELEASE.