与Spring和Jackson完整数据绑定一起休息
-
10-10-2019 - |
题
我正在使用Spring MVC来处理JSON帖子请求。在封面下面,我正在使用jackson JSON处理器上构建的MappingJacksonHttpMessageConverter,并在使用MVC:注释驱动时启用。
我的一项服务收到了一系列措施:
@RequestMapping(value="/executeActions", method=RequestMethod.POST)
public @ResponseBody String executeActions(@RequestBody List<ActionImpl> actions) {
logger.info("executeActions");
return "ACK";
}
我发现杰克逊将请求机构映射到java.util.linkedhashmap项目(简单数据绑定)的列表。相反,我希望该请求绑定到键入对象列表(在这种情况下为“ ActionImpl”)。
我知道,如果您直接使用Jackson的ObjectMapper,这很容易做到:
List<ActionImpl> result = mapper.readValue(src, new TypeReference<List<ActionImpl>>() { });
但是我想知道,当使用Spring MVC和MappingJacksonHtpMessageConverter时,最好的方法是什么。有提示吗?
谢谢
解决方案
我怀疑问题是由于类型擦除,即而不是传递通用参数类型,也许只传递action.getClass()。这将给出等效列表<?>的类型。
如果这是真的,一种可能性是使用中级子类,例如:
public class ActionImplList extends ArrayList<ActionImpl> { }
因为这将保留类型信息,即使仅通过了类。因此:
public @ResponseBody String executeActions(@RequestBody ActionImplList actions)
会做到的。不是最佳的,但应该起作用。
我希望有更多春季MVC知识的人能否阐明为什么没有通过参数类型(也许是一个错误?),但至少有一项工作。
其他提示
我发现您还可以通过使用数组作为@requestbody而不是集合来解决擦除类型问题。例如,以下将有效:
public @ResponseBody String executeActions(@RequestBody ActionImpl[] actions) { //... }
有关您的信息,该功能将在春季3.2中提供(请参阅 https://jira.springsource.org/browse/spr-9570)
我刚刚在当前的M2上进行了测试,它的工作方式就像是一个开箱即用的魅力(无需提供添加注释来提供参数化类型,它将由新的MessageConverter自动解决)
这个问题已经老了,但是我认为我可以做出一些贡献。
就像Staxman指出的那样,这是由于类型擦除。绝对是 应该 有可能,因为你 能够 通过从方法定义进行反思获取通用参数。但是,问题是 httpmessageconverter:
T read(Class<? extends T> clazz, HttpInputMessage inputMessage);
在这里,只有List.Class将传递给该方法。因此,如您所见,无法通过查看方法参数类型来实现httpmessageconverter,该httpmessageconverter可以计算真实类型。
但是,可以编码自己的解决方法 - 您不会使用httpmessageconverter。春季MVC允许您写自己的 WebargumentResolver 这是在标准分辨率方法之前开始的。例如,您可以使用自己的自定义注释(@jsonrequestbody?),该注释直接使用ObjectMapper来解析您的价值。您将能够从该方法提供参数类型:
final Type parameterType= method.getParameterTypes()[index];
List<ActionImpl> result = mapper.readValue(src, new TypeReference<Object>>() {
@Override
public Type getType() {
return parameterType;
}
});
我认为并不是真正打算使用分键的方式,但是ObjectMapper并没有提供更合适的方法。
您是否尝试将该方法声明为:
executeActions(@RequestBody TypeReference<List<ActionImpl>> actions)
我没有尝试过,但是根据您的问题,这是我的第一件事 将 尝试。