JSON(JavaScript Object Notation)是轻量级、跨语言、语法简洁的数据交换格式,是 RESTful API 前后端数据交互的事实标准。 在 Spring Boot 中,Jackson 是官方内置的默认 JSON 处理框架,随 spring-boot-starter-web 自动集成,无需手动配置。它核心完成两大关键操作:
序列化:Java 对象 → JSON 字符串(后端返回数据给前端)
反序列化:JSON 字符串 → Java 对象(接收前端请求体数据)
Spring Web 场景会自动引入 Jackson,无需额外添加依赖;仅处理 Java 8+ 日期(LocalDate/LocalDateTime)时,需补充日期模块:
<!-- Spring Web(自带Jackson核心) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 必须:Java 8 日期格式化支持 -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>接收请求:前端 JSON → Jackson 反序列化 → Controller 方法参数(Java 对象)
返回响应:Java 对象 → Jackson 序列化 → 前端 JSON 数据
注解用于自定义 JSON 转换规则,是企业开发必备,覆盖最常用场景:
用 Lombok 消除冗余 get/set/构造方法
补全完整 CRUD 接口
规范注解使用
增加全局配置,减少重复注解
package com.example.demo.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
/**
* 用户实体类
* Lombok 注解说明:
* @Data:自动生成get/set/toString/equals/hashCode
* @NoArgsConstructor:Jackson 反序列化【必须有无参构造】
* @AllArgsConstructor:全参构造
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
// 序列化规则:值为 null 的字段不输出到 JSON
@JsonInclude(JsonInclude.Include.NON_NULL)
// 忽略前端传递的多余字段,避免报错(企业必备)
// @JsonIgnoreProperties(ignoreUnknown = true)
public class User {
private Integer id;
// 重命名:Java 字段 name → JSON 字段 full_name
@JsonProperty("full_name")
private String name;
// 忽略字段:不返回给前端,也不接收前端数据
@JsonIgnore
private String password;
// 日期格式化:指定格式 + 时区
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private LocalDate dob;
private String email;
}package com.example.demo.controller;
import com.example.demo.model.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
@RestController
@RequestMapping("/api/users")
public class UserController {
// 线程安全集合,模拟数据库存储
private final List<User> userList = new CopyOnWriteArrayList<>();
// 原子ID生成器,保证线程安全
private final AtomicInteger idGenerator = new AtomicInteger(1);
// 初始化测试数据
public UserController() {
userList.add(new User(
idGenerator.getAndIncrement(),
"Vishnu Chauhan",
"secret123",
LocalDate.of(1998,5,20),
"vishnu@example.com"
));
}
// 1. 查询所有用户 GET /api/users
@GetMapping
public List<User> getAllUsers() {
return userList;
}
// 2. 根据ID查询用户 GET /api/users/{id}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Integer id) {
return userList.stream()
.filter(user -> user.getId().equals(id))
.findFirst()
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
// 3. 新增用户 POST /api/users
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
user.setId(idGenerator.getAndIncrement());
userList.add(user);
// REST 规范:新增资源返回 201 状态码
return ResponseEntity.status(HttpStatus.CREATED).body(user);
}
// 4. 全量更新用户 PUT /api/users/{id}
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(
@PathVariable Integer id,
@RequestBody User user
) {
return userList.stream()
.filter(u -> u.getId().equals(id))
.findFirst()
.map(existUser -> {
existUser.setName(user.getName());
existUser.setDob(user.getDob());
existUser.setEmail(user.getEmail());
return ResponseEntity.ok(existUser);
})
.orElse(ResponseEntity.notFound().build());
}
// 5. 删除用户 DELETE /api/users/{id}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Integer id) {
userList.removeIf(user -> user.getId().equals(id));
// REST 规范:删除成功返回 204 无内容
return ResponseEntity.noContent().build();
}
}package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}无需在每个实体类加注解,全局统一配置更简洁,在 application.yml 中配置:
spring:
jackson:
# 全局忽略 null 字段(替代 @JsonInclude)
default-property-inclusion: non_null
# 全局日期格式化
date-format: yyyy-MM-dd HH:mm:ss
# 时区
time-zone: GMT+8
# 格式化输出 JSON(方便调试)
serialization:
indent-output: true优先级规则:注解 > 全局配置(注解可覆盖全局设置)
GET http://localhost:8080/api/users[
{
"id": 1,
"full_name": "Vishnu Chauhan",
"dob": "1998-05-20",
"email": "vishnu@example.com"
}
]验证结果:
name → full_name:@JsonProperty 重命名生效
password 字段消失:@JsonIgnore 忽略生效
日期格式标准化:@JsonFormat 格式化生效
无 null 字段:@JsonInclude 空值过滤生效
Jackson 将 JSON 转为 Java 对象时,必须有无参构造器,Lombok @NoArgsConstructor 可自动生成。
NON_NULL:忽略 null 字段(最常用)
NON_EMPTY:忽略 null + 空字符串 + 空集合
ALWAYS:始终序列化(默认值)
前端传递实体类不存在的字段时,添加注解避免 400 错误:
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {}统一规范:全局配置 Jackson,减少冗余注解
数据安全:密码、密钥等敏感数据必须用 @JsonIgnore 忽略
格式统一:全局固定日期格式、时区、空值处理规则
兼容性:默认忽略前端多余字段,提升接口健壮性
代码简化:必用 Lombok 简化实体类代码
分层清晰:JSON 转换仅在 Controller 层处理,不侵入业务逻辑
核心定位:Jackson 是 Spring Boot 默认 JSON 库,自动完成序列化 / 反序列化
核心注解:@JsonProperty(重命名)、@JsonIgnore(忽略字段)、@JsonFormat(格式化)、@JsonInclude(空值过滤)
必备条件:实体类必须有无参构造器,日期处理需引入专用依赖
最佳方案:全局配置为主,注解为辅,兼顾简洁性与灵活性