Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SpringMVC4.0中JSON表单参数的自动转换_Java_Json_Spring_Spring Mvc_Jackson - Fatal编程技术网

Java SpringMVC4.0中JSON表单参数的自动转换

Java SpringMVC4.0中JSON表单参数的自动转换,java,json,spring,spring-mvc,jackson,Java,Json,Spring,Spring Mvc,Jackson,我正在尝试构建一个SpringMVC控制器,它将接收一个带有JSON格式参数的发布表单,并让Spring自动将其转换为Java对象 请求内容类型为application/x-www-form-urlencoded 包含JSON字符串的参数名为data.JSON 这是控制器: @Controller public class MyController { @RequestMapping(value = "/formHandler", method = RequestMethod.POS

我正在尝试构建一个SpringMVC控制器,它将接收一个带有JSON格式参数的发布表单,并让Spring自动将其转换为Java对象

  • 请求内容类型为
    application/x-www-form-urlencoded
  • 包含JSON字符串的参数名为
    data.JSON
这是控制器:

@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
如果我读对了,Jackson-JSON转换是由Content-Type
application/JSON
触发的,我显然不能使用它,因为这是一个表单POST(我不控制POST部分)


是否可以让Spring将JSON字符串转换为MyMessage的实例,或者我应该放弃,将其作为字符串读取并自己执行转换?

Spring通过反射调用您的
@RequestMapping
方法。要解析要传递给调用的每个参数,它使用
HandlerMethodArgumentResolver
的实现。对于带注释的参数
@RequestParam
,它使用
requestparamethodargumentresolver
。此实现将请求参数绑定到单个对象,通常是
字符串
或一些
数字
类型

然而,您的用例更为罕见。您很少会收到
json
作为请求参数,这就是为什么我认为您应该重新考虑您的设计,但是如果您没有其他选择,您需要注册一个自定义
属性编辑器
,该编辑器将负责将请求参数的
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
接口的所有方法,因此我们可以使用
PropertyEditorSupport
,这是
PropertyEditor
的一个有用的默认实现。我们只需使用我们想要的JSON解析器的任何一种风格来实现我们关心的两种方法。我使用了
Gson
,因为它是可用的

当Spring看到它有一个您请求的请求参数时,它将检查参数类型,找到类型
MyMessage
,并查找该类型的已注册
PropertyEditor
。它将找到它,因为我们注册了它,然后它将使用它来转换值

您可能需要实现
PropertyEditor
的其他方法,具体取决于接下来要做的事情


我的建议是永远不要将JSON作为请求参数发送。将请求内容类型设置为
application/json
,并将
json
作为请求主体发送。然后使用
@RequestBody
对其进行解析。

您也可以像这样使用
@RequestPart

@RequestMapping(value = "/issues", method = RequestMethod.POST, headers = "Content-Type=multipart/form-data")
public String uploadIssue(@RequestParam("image") MultipartFile file, @RequestPart("issue") MyMessage issue)

我不控制客户端应该遵循服务器规范的发布部分,而不是相反。客户端是我无法控制的第三方webhook机制。但您的陈述让我好奇,HTTP规范中是否有禁止使用表单字段/post参数发送JSON数据的内容?不,没有,但对于REST,将其放在正文中已成为惯例。“我的建议是永远不要将JSON作为请求参数发送”。我同意,但我并没有控制发送端,我只是为第三方webhook实现了一个接收器。它是为Mandrill实现的吗?我猜他们的客户端只能接收表单参数而不能接收内容体。@NickSpacek不,这是一种接收调用的机制。您并不总是可以控制浏览器代码,例如ExtJS数据存储小部件将JSON编码的字符串作为请求参数发送以支持筛选,因此,在服务器端确实需要类似于此的解决方案。FWIW-Slack对操作回调做了类似的事情,基本上主体是:
payload=
不幸的是,
@RequestPart
注释不能与内容类型
应用程序/x-www-form-urlencoded
一起使用。