java - Spring MVC 4.0中JSON表单参数的自动转换

标签 java json spring spring-mvc jackson

我正在尝试构建一个 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/

相关文章:

java - 从 xsd :choice element 自定义 JAXB 2.0 生成的方法名称

java - JAX-RS - 没有根节点的 JSON

java - Spring @ModelAttribute 不应该将属性添加到 View 中吗?

java - 使用 Java Servlet 中的方法填充 JSP 文本区域

java - 如何在HBase中设置In-Memory

java - MongoDB MapReduce 比纯 Java 处理慢很多?

php - 问题 json_encode utf-8

javascript - 使用 Angular 和 JSON 填充下拉列表

android - 如何从 Android 应用程序向 Rails 应用程序发送 POST 请求?

java - 如何将 SQL 转换为 JPQL 查询?