我正在尝试构建一个 Spring MVC Controller ,它将接收带有 JSON 格式参数的 POSTed 表单,并让 Spring 自动将其转换为 Java 对象。
- 请求内容类型为
application/x-www-form-urlencoded
- 包含JSON字符串的参数名称是
data.json
这是 Controller :
@Controller
public class MyController {
@RequestMapping(value = "/formHandler", method = RequestMethod.POST)
public @ResponseBody String handleSubscription(
@RequestParam("data.json") MyMessage msg) {
logger.debug("id: " + msg.getId());
return "OK";
}
}
这就是 MyMessage 对象的样子:
public class MyMessage {
private String id;
// Getter/setter omitted for brevity
}
也许并不奇怪,发布带有参数 data.json={"id":"Hello"} 的表单会导致 HTTP 错误 500,并出现以下异常:
org.springframework.beans.ConversionNotSupportedException:
Failed to convert value of type 'java.lang.String' to required type 'MyMessage'
nested exception is java.lang.IllegalStateException:
Cannot convert value of type [java.lang.String] to required type [MyMessage]: no matching editors or conversion strategy found
如果我阅读 MappingJackson2HttpMessageConverter docs正确地,Jackson JSON 转换是由 Content-Type application/json
触发的,我显然不能使用它,因为这是一个 POST 表单(而且我不控制 POSTing 部分)。
是否可以让 Spring 将 JSON 字符串转换为 MyMessage 的实例,或者我应该放弃,将其作为字符串读取并自己执行转换?
最佳答案
Spring 通过反射调用您的@RequestMapping
方法。为了解析要传递给调用的每个参数,它使用了 HandlerMethodArgumentResolver
的实现。对于@RequestParam
注解参数,它使用RequestParamMethodArgumentResolver
。此实现将请求参数绑定(bind)到单个对象,通常是 String
或某些 Number
类型。
但是,您的用例比较少见。你很少收到 json
作为请求参数,这就是我认为你应该重新考虑你的设计的原因,但如果你别无选择,你需要注册一个自定义的PropertyEditor
负责将请求参数的 json
值转换为您的自定义类型。
在 @Controller
类的 @InitBinder
注释方法中注册很简单
@InitBinder
public void initBinder(WebDataBinder dataBinder) {
dataBinder.registerCustomEditor(MyMessage.class, new PropertyEditorSupport() {
Object value;
@Override
public Object getValue() {
return value;
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
value = new Gson().fromJson((String) text, MyMessage.class);
}
});
}
在这种特殊情况下,我们不需要 PropertyEditor
接口(interface)的所有方法,因此我们可以使用 PropertyEditorSupport
,它是 的一个有用的默认实现属性编辑器
。我们只需使用我们想要的任何一种 JSON 解析器来实现我们关心的两种方法。我使用 Gson
因为它可用。
当 Spring 看到它有一个你请求的请求参数时,它会检查参数类型,找到类型 MyMessage
并为该类型寻找一个注册的 PropertyEditor
.它会找到它,因为我们注册了它,然后它将使用它来转换值。
您可能需要实现 PropertyEditor
的其他方法,具体取决于您下一步要做什么。
我的建议是永远不要将 JSON 作为请求参数发送。将您的请求内容类型设置为 application/json
并将 json
作为请求的主体发送。然后使用@RequestBody
解析。
关于java - Spring MVC 4.0中JSON表单参数的自动转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20622359/