Java Spring MVC 4.0中JSON表单参数的自动转换
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20622359/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Automatic conversion of JSON form parameter in Spring MVC 4.0
提问by Jon Ekdahl
I am trying to build a Spring MVC controller which will receive a POSTed form with a parameter in JSON format, and have Spring automatically convert it to a Java object.
我正在尝试构建一个 Spring MVC 控制器,它将接收带有 JSON 格式参数的 POSTed 表单,并让 Spring 自动将其转换为 Java 对象。
- Request content type is
application/x-www-form-urlencoded
- The name of the parameter that contains a JSON string is
data.json
- 请求内容类型为
application/x-www-form-urlencoded
- 包含 JSON 字符串的参数名称为
data.json
This is the 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";
}
}
And this is what the MyMessage object looks like:
这就是 MyMessage 对象的样子:
public class MyMessage {
private String id;
// Getter/setter omitted for brevity
}
Perhaps not surprisingly, posting a form with parameter data.json={"id":"Hello"} results in HTTP error 500 with this exception:
也许并不奇怪,发布带有参数 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
If I read the MappingHymanson2HttpMessageConverter docscorrectly, Hymanson JSON conversion is triggered by Content-Type application/json
, which I obviously cannot use since this is a form POST (and I don't control the POSTing part).
如果我正确阅读了MappingHymanson2HttpMessageConverter 文档,Hymanson JSON 转换是由 Content-Type 触发的application/json
,我显然不能使用它,因为这是一个表单 POST(并且我不控制 POSTing 部分)。
Is it possible to get Spring to convert the JSON string into an instance of MyMessage, or should I just give up, read it as a String and perform the conversion myself?
是否有可能让 Spring 将 JSON 字符串转换为 MyMessage 的实例,或者我应该放弃,将其作为字符串读取并自己执行转换?
采纳答案by Sotirios Delimanolis
Spring invokes your @RequestMapping
methods with reflection. To resolve each argument it's going to pass to the invocation, it uses implementations of HandlerMethodArgumentResolver
. For @RequestParam
annotated parameters, it uses RequestParamMethodArgumentResolver
. This implementation binds a request parameter to a single object, typically a String
or some Number
type.
Spring@RequestMapping
通过反射调用您的方法。为了解析它将传递给调用的每个参数,它使用HandlerMethodArgumentResolver
. 对于带@RequestParam
注释的参数,它使用RequestParamMethodArgumentResolver
. 此实现将请求参数绑定到单个对象,通常是一个String
或某个Number
类型。
However, your use case is a little more rare. You rarely receive json
as a request parameter, which is why I think you should re-think your design, but if you have no other choice, you need to register a custom PropertyEditor
that will take care of converting the request parameter's json
value into your custom type.
但是,您的用例比较少见。您很少收到json
请求参数,这就是为什么我认为您应该重新考虑您的设计,但是如果您别无选择,您需要注册一个自定义PropertyEditor
,它将负责将请求参数的json
值转换为您的自定义类型。
Registration is simple in an @InitBinder
annotated method in your @Controller
class
@InitBinder
在您的@Controller
类中的带注释的方法中注册很简单
@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);
}
});
}
In this particular case, we don't need all the methods of the PropertyEditor
interface, so we can use PropertyEditorSupport
which is a helpful default implementation of PropertyEditor
. We simply implement the two methods we care about using whichever flavor of JSON parser we want. I used Gson
because it was available.
在这种特殊情况下,我们不需要PropertyEditor
接口的所有方法,因此我们可以使用PropertyEditorSupport
这是PropertyEditor
. 我们只需使用我们想要的任何类型的 JSON 解析器来实现我们关心的两种方法。我使用Gson
是因为它可用。
When Spring sees that it has a request parameter that you requested, it will check the parameter type, find the type MyMessage
and look for a registered PropertyEditor
for that type. It will find it because we registered it and it it will then use it to convert the value.
当 Spring 看到它有一个您请求的请求参数时,它会检查参数类型,查找类型MyMessage
并查找该类型的注册PropertyEditor
。它会找到它,因为我们注册了它,然后它会使用它来转换值。
You might need to implement other methods of PropertyEditor
depending on what you do next.
您可能需要实施其他方法,PropertyEditor
具体取决于您接下来要做什么。
My recommendation is to never send JSON as a request parameter. Set your request content type to application/json
and send the json
as the body of the request. Then use @RequestBody
to parse it.
我的建议是永远不要将 JSON 作为请求参数发送。将您的请求内容类型设置为application/json
并json
作为请求正文发送。然后@RequestBody
用来解析它。
回答by feht
You can also use @RequestPart
like this:
你也可以@RequestPart
这样使用:
@RequestMapping(value = "/issues", method = RequestMethod.POST, headers = "Content-Type=multipart/form-data")
public String uploadIssue(@RequestParam("image") MultipartFile file, @RequestPart("issue") MyMessage issue)