1. 概述
在这篇教程中,我们将深入探讨如何在 Spring MVC 中处理 JSON 参数。
首先会简单介绍 JSON 参数的背景知识,然后重点讲解如何通过 POST 和 GET 请求发送 JSON 参数。
2. Spring MVC 中的 JSON 参数
使用 JSON 来发送或接收数据是 Web 开发中的常见做法。JSON 的层次结构提供了一种更紧凑、更易读的方式来表示 HTTP 请求参数。
默认情况下,Spring MVC 提供了对简单数据类型(如 String
)的开箱即用的数据绑定支持。它底层使用的是 一系列内置的属性编辑器。
但在实际项目中,我们往往需要绑定更复杂的数据类型。例如,将 JSON 参数直接映射为一个模型对象就非常实用。
3. 使用 POST 发送 JSON 数据
Spring 提供了一种简单直接的方式来通过 POST 请求发送 JSON 数据。借助 @RequestBody 注解,Spring 可以自动将请求体中的 JSON 数据反序列化为目标模型对象。
通常我们不需要手动解析请求体,可以借助 Jackson 库 来完成这些繁重的工作。
下面来看一个例子,如何在 Spring MVC 中通过 POST 请求发送 JSON 数据。
首先,定义一个模型类来表示 JSON 数据,例如 Product
类:
public class Product {
private int id;
private String name;
private double price;
// 默认构造函数 + getter + setter
}
然后,定义一个处理 POST 请求的接口方法:
@PostMapping("/create")
@ResponseBody
public Product createProduct(@RequestBody Product product) {
// 自定义业务逻辑
return product;
}
可以看到,只需要给参数加上 @RequestBody
注解,就能自动将客户端发送的 JSON 数据绑定到 Product
对象中。
接下来,使用 cURL 来测试这个接口:
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
只支持简单的数据类型,比如 int
和 String
。
因此,如果想通过 GET 请求传递 JSON 数据,我们需要将 JSON 作为字符串参数传递。
问题来了:如何将这个字符串形式的 JSON 参数转换为 Product
对象?
答案很简单!Jackson 提供的 ObjectMapper
类可以轻松实现 JSON 字符串到 Java 对象的转换。
下面来看具体实现。
首先,在 Controller 中添加一个处理 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
对象。
但如果你更习惯像使用 @RequestBody
一样直接传 Product
对象,那该怎么办?
Spring 提供了更优雅的解决方案:自定义属性编辑器。
首先,创建一个自定义属性编辑器,用于将字符串形式的 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);
}
}
}
接着,修改 Controller 方法,让参数直接接收 Product
类型:
@GetMapping("/get2")
@ResponseBody
public Product get2Product(@RequestParam Product product) {
// 自定义业务逻辑
return product;
}
最后一步,在 Controller 中注册这个自定义编辑器:
@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 中处理 JSON 参数的几种常见方式:
- 通过
@RequestBody
处理 POST 请求中的 JSON 数据 - 通过
@RequestParam
+ObjectMapper
处理 GET 请求中的 JSON 字符串 - 使用自定义属性编辑器实现更优雅的类型转换
一如既往,示例代码可以在 GitHub 上找到。