且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Spring MVC:无法反序列化超出 START_ARRAY 令牌的实例

更新时间:2022-10-18 16:27:30

它不编译的原因是因为在 Java 中不可能传递泛型类型参数的类,因为它们在运行时不存在.

这里有两个选项,使用数组 (LookupChoice[]) 并在必要时将其转换为 List:

restTemplate.getForObject(url, LookupChoice[]);

或者你可以使用ParameterizedTypeReference:

restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference>() {}).getBody()

虽然它是一个接口,所以要么继承它,要么使用匿名类,就像我在上面的代码示例中所做的那样.

另外,如果我没记错的话,ParameterizedTypeReference 只适用于 exchange() 方法,所以你会得到一个 ResponseEntity而不是您的原始对象,因此您必须使用 getBody() 方法.

I have been beating my head against this for a while now and still no joy. I am new to Spring and could really use some help.

I am trying to use Spring Boot to return a list of codes from a DB table. When I call my REST controller from a URL in a browser...

Example URL: localhost:8081/cis/utl/lookupchoice/O.s/

It returns this:

[
{"lookupId":10,"choiceGroup":"O.s","choiceCode":null,"displayLabel":"Pending","hidden":false,"displayOrder":1},
{"lookupId":11,"choiceGroup":"O.s","choiceCode":null,"displayLabel":"Active","hidden":false,"displayOrder":2},
{"lookupId":12,"choiceGroup":"O.s","choiceCode":null,"displayLabel":"Archived","hidden":false,"displayOrder":3},
{"lookupId":13,"choiceGroup":"O.s","choiceCode":null,"displayLabel":"Placeholder","hidden":false,"displayOrder":4}
]

But, I get an error message when trying to run this from a client controller. The call looks like this:

//
//Compiles but does not work
LookupChoice lookupChoice = restTemplate.getForObject(REST_URI+"/utl/lookupchoice/O.s/",
         LookupChoice.class);

The error: nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.MyPakage.repository.LookupChoice out of START_ARRAY token

Assuming the error occurs because an array is returned instead of a single object, I changed the code to this:

//
//Does not compile
Iterable<LookupChoice> lookupChoice = restTemplate.getForObject(REST_URI+"/utl/lookupchoice/U.r/",
         Iterable<LookupChoice.class>);

But, now I get an error in Intellij. It's indicating that an "Expression expected" for the Iterable<LookupChoice.class> param, and I can't get past this.

Thank you for your time and assistance, Ed

Thanks for your reply. I opted for this and it all seems to work now. Thanks for your help!

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Object[]> responseEntity;
Object[] lookupChoice;

responseEntity = restTemplate.getForEntity(REST_SERVICE_URI+"/utl/lookupchoice/O.s/" , Object[].class);
lookupChoice = responseEntity.getBody();
model.addAttribute("Status", lookupChoice);

The reason it doesn't compile is because it's impossible in Java to pass a class of generic type parameters because they don't exist at runtime.

You have two options here, either use an array (LookupChoice[]) and convert it to a List<LookupChoice> if necessary:

restTemplate.getForObject(url, LookupChoice[]);

Or you can use the ParameterizedTypeReference:

restTemplate.exchange(url, HttpMethod.GET, null, new ParameterizedTypeReference<List<LookupChoice>>() {}).getBody()

It is an interface though, so either subclass it or use an anonymous class like I did in the code example above.

Also, ParameterizedTypeReference only works on the exchange() method if I'm not mistaken, so you'll get a ResponseEntity in stead of your raw object, so you'll have to use the getBody() method.