Spring MVC 处理 JSON 参数
1、概览
本文将带你了解如何在 Spring MVC 中处理 POST 和 GET 请求中发送 JSON 参数。
2、Spring MVC 中的 JSON 参数
使用 JSON 发送或接收数据是 Web 开发人员的常见做法。JSON 字符串的分层结构为 HTTP 请求参数提供了一种更紧凑、更易于人类阅读的表示方式。
默认情况下,Spring MVC 通过了一系列内置的底层 Property Editor 为 String
等简单数据类型提供开箱即用的数据绑定。
但是,在实际项目中,可能需要绑定更复杂的数据类型。例如:将 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;
}
如你所见,用 @RequestBody
对 product
参数进行注解就可以绑定客户端发送的 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
注解一般只用于 int
和 String
等简单数据类型。
因此,要发送 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