Spring MVC REST using @RequestBody List <?> Returns HTTP 400 syntactically incorrect

I am using Spring 4 + Jackson 2 and wrote a fully functional POST method using @RequestBody in a custom class. This method has no problem with dismantling the object.

@ResponseBody
@RequestMapping(value="store", method = RequestMethod.POST)
public ServiceResponse store(@RequestBody CustomClass list) {
    ...
}

// Request: { code: "A", amount: 200 }

      

When I tried to add another method to handle a collection of the same class, my POST requests were returning with the following error.

HTTP Status 400: The request sent by the client was syntactically incorrect.

I note that this error usually occurs when the JSON provided does not match the entity class. However, all I do is represent an array of the same object instead of the object itself, which has already proven to work.

@ResponseBody
@RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(@RequestBody List<CustomClass> list) {
    ...
}

// Request: [{ code: "A", amount: 200 }, { code: "B", amount: 400 }]

      

Did I miss something?

+3


source to share


3 answers


The answer is that Spring 4 doesn't actually get rid of type erasure, unlike what some other solutions suggest. While experimenting with debugging with manual unmarshalling, I decided to just handle this step myself, instead of an implicit cast that I have no control over. I hope someone comes along and proves that I am wrong by demonstrating a more intuitive solution though.

@ResponseBody
@RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(@RequestBody String json) {
    try {
        List<CustomClass> list = new ObjectMapper().readValue(json, new TypeReference<List<CustomClass>>() { });
        ...
    } catch (Exception e) {
        ...
    }
}

      

Bonus: right after I got this working, I ran into this exception:

IllegalStateException: There was already a POJO for id



If anyone gets this, it is because the objects in the list are referencing some kind of object that is already referencing another item in the list. I could work around this as this object was identical across my entire collection, so I just removed the JSON-side reference from all but the first object. Then I added the missing links after the JSON was unarmored into the List object.

Two layers for Java 8 users (user object reference was the problem in my case):

User user = list.get(0).getUser();
list.stream().filter(c -> c.getUser() == null).forEach(t -> t.setUser(user));

      

-1


source


In Java, type information for generics is erased at runtime, so Spring sees yours List<CustomClass> object

as List<Object> object

, so it can't figure out how to parse it.

One way to solve it is to grab the type information by creating a wrapper class for your list, for example:



public class CustomClassList extends ArrayList<CustomClass> {
}

      

0


source


Sergey is right that the problem is related to type erasure. The easiest way out is to bind to an array, so

@ResponseBody
@RequestMapping(value="store-bulk", method = RequestMethod.POST)
public ServiceResponse storeBulk(@RequestBody CustomClass[] object) {
    ...
}

      

0


source







All Articles