Spring MVC 处理 JSON 参数

1、概览

本文将带你了解如何在 Spring MVC 中处理 POST 和 GET 请求中发送 JSON 参数。

2、Spring MVC 中的 JSON 参数

使用 JSON 发送或接收数据是 Web 开发人员的常见做法。JSON 字符串的分层结构为 HTTP 请求参数提供了一种更紧凑、更易于人类阅读的表示方式。

默认情况下,Spring MVC 通过了一系列内置的底层 Property EditorString 等简单数据类型提供开箱即用的数据绑定。

但是,在实际项目中,可能需要绑定更复杂的数据类型。例如:将 JSON 参数映射到 Model Object。

3、使用 POST 请求发送 JSON

Spring 提供了一种简单的方式来处理 POST 请求发送 JSON 数据。内置的 @RequestBody 注解可以自动将请求体中的 JSON 数据反序列化为特定的 Model 对象。

通常情况下,无需自己解析请求体,Spring MVC 会使用 Jackson 库来完成所有的工作。

首先,创建一个 Model 对象来表示传递的 JSON 数据。例如 Product 类:

public class Product {

    private int id;
    private String name;
    private double price;

    // 构造函数、get、set 方法省略

}

其次,定义一个接受 POST 请求的 Spring Handler 方法:

@PostMapping("/create")
@ResponseBody
public Product createProduct(@RequestBody Product product) {
    // 业务逻辑 ...
    return product;
}

如你所见,用 @RequestBodyproduct 参数进行注解就可以绑定客户端发送的 JSON 数据。

现在,使用 cURL 测试 POST 请求:

curl -i \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-X POST --data \
  '{"id": 1,"name": "Asus Zenbook","price": 800}' "http://localhost:8080/spring-mvc-basics-4/products/create"

4、使用 GET 请求发送 JSON

Spring MVC 提供 @RequestParam 来从 GET 请求中提取查询参数。不过,与 @RequestBody 不同,@RequestParam 注解一般只用于 intString 等简单数据类型。

因此,要发送 JSON,需要将 JSON 参数定义为简单的字符串。

这里最大的问题是 如何将 JSON 参数(String)转换为 Product 类对象?

非常简单!Jackson 的 ObjectMapper 类提供了将 JSON 字符串转换为 Java 对象的灵活方法。

现在,来看看如何在 Spring MVC 中通过 GET 请求发送 JSON 参数。

首先,要在 Controller 中创建另一个 Handler 方法来处理 GET 请求:

@GetMapping("/get")
@ResponseBody
public Product getProduct(@RequestParam String product) throws JsonMappingException, JsonProcessingException {
    Product prod = objectMapper.readValue(product, Product.class);
    return prod;
}

如上,readValue() 方法允许将 JSON 参数 product 直接反序列化为 Product 类的实例。 这里把 JSON 格式的查询参数定义为了 String 对象,我们需要自己手动使用 ObjectMapper 进行转换,这有点麻烦。能不能和使用 @RequestBody 注解一样,让框架自动地把 JSON 查询参数封装为对象?

Spring 通过自定义 Property Editor 提供了简洁灵活的解决方案。

首先,创建一个自定义 Property Editor,以封装将 String 形式的 JSON 参数转换为 Product 对象的逻辑:

public class ProductEditor extends PropertyEditorSupport {

    private ObjectMapper objectMapper;

    public ProductEditor(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        if (StringUtils.isEmpty(text)) {
            setValue(null);
        } else {
            Product prod = new Product();
            try {
                prod = objectMapper.readValue(text, Product.class);
            } catch (JsonProcessingException e) {
                throw new IllegalArgumentException(e);
            }
            setValue(prod);
        }
    }

}

接下来,将 JSON 参数绑定到 Product 类对象:

@GetMapping("/get2")
@ResponseBody
public Product get2Product(@RequestParam Product product) {
    // 自定义逻辑
    return product;
}

最后,需要在 Spring Controller 中注册 ProductEditor

@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.registerCustomEditor(Product.class, new ProductEditor(objectMapper));
}

注意,需要对 JSON 参数进行 URL 编码,以确保安全传输。

因此,对于如下请求:


GET /spring-mvc-basics-4/products/get2?product={"id": 1,"name": "Asus Zenbook","price": 800}

需要被编码为:

GET /spring-mvc-basics-4/products/get2?product=%7B%22id%22%3A%201%2C%22name%22%3A%20%22Asus%20Zenbook%22%2C%22price%22%3A%20800%7D

5、总结

本文介绍了如何在 Spring MVC 中处理 POST 请求或 GET 请求提交的 JSON 参数。


Ref:https://www.baeldung.com/spring-mvc-send-json-parameters