将@RequestBody 转换为对象

Posted

技术标签:

【中文标题】将@RequestBody 转换为对象【英文标题】:Converting @RequestBody to an object 【发布时间】:2011-08-18 21:34:30 【问题描述】:

伙计们,我已经做了足够多的研究,但仍然找不到解决方案。

简而言之,我只是将 url 编码的表单数据传递给 Controller 方法,并尝试将其转换为具有日期和整数的域对象。

@RequestMapping(value = "/savePassport", method = RequestMethod.POST)
    public @ResponseBody
    AjaxResponse savePassport(@RequestBody StaffPassport passport, HttpServletResponse response) 

    // Some operations.

员工护照如下所示:

import java.sql.Date;

public class StaffPassport 

    private int staffId;
    private String passportNumber;
    private String placeOfIssue;
    private Date issueDate;
    private Date expiryDate;
    private String spouseName;
    private String oldPassportRef;
    private String visaInfo;
    private String description;
//gets/sets

当我调用 /savePassport 时,我得到不受支持的媒体异常。我猜这和选角有关。

我不能正常工作。当然,我可以使用 @RequestParam 捕获单个表单数据并手动进行转换,但这不是框架的重点,不是吗?

我哪里出错了?你是对的。我是 Spring 的初学者,但我喜欢它。

【问题讨论】:

问得好,ResponseBody 效果很好,但是没有人知道如何让RequestBody 自动绑定到一个bean 上?这很奇怪...... 【参考方案1】:

您似乎使用了错误的注释。 @RequestBody 用于接受在其正文中具有任意内容的请求,例如 JSON、某些应用程序定义的 XML、逗号分隔的变量.. 等等。并使用您在调度程序 servlet 中配置的编组器将其转换为对象。

如果您只想让 Spring 为您绑定一个普通的旧表单帖子到支持对象上,则在方法参数上放置的正确注释是 @ModelAttribute

【讨论】:

我没有使用
来使用基于 spring 的表单。我只是通过序列化表单和调用控制器方法来使用 ajax 调用。我也尝试过@ModelAttribute。但同样,我猜日期转换似乎存在一些问题。如果有什么特殊的配置要为此做,你能建议吗?
完成这项工作的类是 WebDataBinder。手动完成会很痛苦,因为其中有很多配置。 是的,java.sql.Date 没有默认的属性编辑器。您需要注册自己的属性编辑器,以便使用 @InitBinder 将字符串转换为日期。 我的回复有点晚。你说的对。我使用了@ModelAttribute 和 WebDataBinder 的组合,我得到了解决方案。我使用了错误的注释。【参考方案2】:

如果您使用 jQuery 发布 JSON 对象,并且希望 Spring 能够使用 @RequestBody 处理它,请在您的数据中使用 JSON.stringify(....)。举个例子:

var data =  "id": 3, "name": "test" 
$.post("processJsonData.html",JSON.stringify(data), function(data)
    ...
  
);

如果你不使用 JSON.stringify() 那么你会将数据作为表单数据提交,Spring 会告诉你你有一个不受支持的媒体类型。

【讨论】:

【参考方案3】:

首先确定你有

<mvc:annotation-driven /> 

在你的 Spring 配置文件中。这是在 SPring MVC 中使用 JSOn 所必需的。

其次,我建议您测试对服务器的请求是否具有 application/json 内容类型。我相信 Fiddler2 会帮助你做到这一点。

第三,但我不确定,尝试将 POJO 中的 Date 项从 SQL 类型更改为常规 java 类型。

更新: 刚刚查看了表单,您的“接受”HTTP 标头似乎也应该是 application/json。请也使用 Fiddler2 测试此问题。

【讨论】:

【参考方案4】:

我假设您发布 JSON 并希望 Spring 转换为 StaffPassport。如果您收到 Unsupported media 异常,那是因为 Spring 无法找到合适的方式来执行转换。

要让 Spring 转换 JSON,它需要 Jackson——确保您的项目中有 Jackson jar。如果这是一个基于 Maven 的项目,您可以将 jackson-mapper-asl 工件 ID 添加到您的 pom.xml。这应该会给你 jackson-mapper 和 jackson-core jars。

编辑:我应该提到这适用于 Spring 3(我最近遇到了这个问题)。我不确定以前版本的 Spring 还需要什么。

【讨论】:

【参考方案5】:

检查 HttpMessageConverter 接口及其实现。您可以编写自己的实现来将其转换为您想要的域模型。当控件到达您的方法时,您可以像传递域模型对象一样访问它。

【讨论】:

【参考方案6】:

好的,我想我应该完善我的答案。我没有在 spring-mvc 项目中使用它的直接经验,而是在 spring-integration 中使用它。我很确定适用的媒体类型(application/x-url-form-encoded)已经被 Spring 框架处理并转换为 MultiMap;因此,就像任何其他地图一样,从中检索值,键值是您的表单变量并填充您的业务模型。

HTH。

【讨论】:

请更新您的原始答案并进行任何澄清。

以上是关于将@RequestBody 转换为对象的主要内容,如果未能解决你的问题,请参考以下文章

Spring注解@ResponseBody,@RequestBody

@RequestBody 映射复杂的 json 对象

@RequestBody 没有将 JSON 映射到 Java 对象 - Spring Boot

如何在@RequestBody 中自定义将字符串转换为枚举?

@RequestBody, @ResponseBody 注解理解

@RequestBody使用