返回JSON数据用什么注解?一文Spring Boot常用JSON注解
在Java Web开发中,尤其是Spring Boot框架中,前后端数据交互的核心往往是JSON格式的数据,为了简化Java对象与JSON字符串之间的转换,Spring Boot提供了多种注解来标记接口返回值、方法参数或对象属性,使其自动序列化为JSON或反序列化为Java对象,本文将详细介绍这些常用的JSON注解,帮助你在开发中灵活选择和使用。
核心注解:@ResponseBody与@RestController
在Spring Boot中,最基础也最核心的两个用于返回JSON数据的注解是@ResponseBody和@RestController。
@ResponseBody:标记方法返回值为响应体
@ResponseBody是Spring框架提供的注解,用于标记方法的返回值,使其直接作为HTTP响应体的内容(而不是跳转到视图页面),默认情况下,Spring会使用Jackson库(jackson-databind)将返回的Java对象序列化为JSON字符串。
使用场景:
- 当某个接口需要返回JSON数据,但当前类已经使用
@Controller标记时,可在方法上添加@ResponseBody。
示例:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
@GetMapping("/user")
@ResponseBody
public User getUser() {
User user = new User(1L, "张三", 25);
return user; // 返回的User对象会被序列化为JSON字符串
}
}
// User类
class User {
private Long id;
private String name;
private Integer age;
// 构造方法、getter/setter省略
}
访问结果:
浏览器或客户端访问/user接口时,会直接返回JSON字符串:
{"id":1,"name":"张三","age":25}。
@RestController:组合注解,简化开发
@RestController是Spring Boot 3.0+提供的组合注解,相当于@Controller + @ResponseBody,当一个类被@RestController标记时,该类下的所有方法都会默认将返回值作为响应体,无需再单独添加@ResponseBody。
使用场景:
- 专门用于编写RESTful API的控制器类,所有接口均返回JSON数据。
示例:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/user")
public User getUser() {
return new User(1L, "李四", 30);
}
}
// 访问结果同上,无需@ResponseBody注解
JSON序列化控制注解:@JsonFormat与@JsonSerialize
当Java对象中的属性需要特殊格式化(如日期、枚举)或自定义序列化逻辑时,可以通过以下注解控制JSON的生成方式。
@JsonFormat:格式化日期/时间/数字
@JsonFormat是Jackson提供的注解,用于指定Java属性与JSON字段的映射格式,常用于日期、时间、数字等类型的格式化。
常用属性:
pattern:日期/时间格式(如"yyyy-MM-dd HH:mm:ss")。timezone:时区(如"GMT+8")。
示例:
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
@RestController
public class OrderController {
@GetMapping("/order")
public Order getOrder() {
Order order = new Order();
order.setId(1001L);
order.setCreateTime(new Date()); // 当前时间
return order;
}
}
class Order {
private Long id;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
// getter/setter省略
}
访问结果:
{"id":1001,"createTime":"2023-10-01 14:30:00"}(假设当前时间为2023年10月1日14:30:00)。
@JsonSerialize:自定义序列化逻辑
当@JsonFormat无法满足复杂序列化需求时,可以使用@JsonSerialize注解指定自定义的序列化器(需实现JsonSerializer接口)。
示例:
假设User类中的age字段需要序列化为“xx岁”的格式:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
@RestController
public class UserController {
@GetMapping("/user")
public User getUser() {
User user = new User(1L, "王五", 28);
return user;
}
}
class User {
private Long id;
private String name;
@JsonSerialize(using = AgeSerializer.class)
private Integer age;
// getter/setter省略
}
// 自定义年龄序列化器
class AgeSerializer extends JsonSerializer<Integer> {
@Override
public void serialize(Integer age, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString(age + "岁");
}
}
访问结果:
{"id":1,"name":"王五","age":"28岁"}。
JSON反序列化控制注解:@JsonDeserialize
与@JsonSerialize对应,@JsonDeserialize用于指定自定义的反序列化器(需实现JsonDeserializer接口),解决JSON字符串到Java对象的转换问题(如日期字符串转Date对象)。
示例:
假设前端传入的createTime是字符串“2023-10-01”,需要反序列化为Date对象:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
@RestController
public class OrderController {
@PostMapping("/order")
public String createOrder(@RequestBody Order order) {
System.out.println(order.getCreateTime()); // 输出反序列化后的Date对象
return "success";
}
}
class Order {
private Long id;
@JsonDeserialize(using = CustomDateDeserializer.class)
private Date createTime;
// getter/setter省略
}
// 自定义日期反序列化器
class CustomDateDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
return sdf.parse(p.getText());
} catch (Exception e) {
throw new IOException("日期格式错误,请使用yyyy-MM-dd");
}
}
}
请求示例:
POST /order
Content-Type: application/json
{
"id": 1002,
"createTime": "2023-10-01"
}
后台输出:
Mon Oct 01 00:00:00 CST 2023。
字段映射控制注解:@JsonProperty、@JsonIgnore与@JsonIgnoreProperties
当JSON字段名与Java属性名不一致,或需要忽略某些字段时,可通过以下注解进行控制。
@JsonProperty:指定JSON字段名
默认情况下,Java属性名会直接作为JSON字段名(如userName→userName),若需要修改(如userName→user_name),可使用@JsonProperty注解。
示例:
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/user")
public User getUser() {
User user = new User();
user.setUserName("赵六");
user.setAge(25);
return user;
}
}
class User {
@JsonProperty("user_name")
private String userName;
private Integer age;
// getter/setter省略
}
访问结果:
{"user_name":"赵六","age":25}。
@JsonIgnore:忽略字段
若某个Java属性不需要参与JSON序列化/反序列化(如密码等敏感信息),可使用@JsonIgnore注解。
示例:
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/user")
public User getUser() {
User user = new User();
user.setUserName("钱七");
user.setPassword("123456");
return user;
}
}
class User {
private String userName;
@JsonIgnore
private String password;


还没有评论,来说两句吧...