【无标题】

Jackson 详细教程:Java 中最好用的 JSON 处理库之一

在 Java 开发里,只要你要和前端、接口、微服务打交道,就几乎绕不开 JSON

而在 Java 生态中,最常用的 JSON 处理库之一就是 Jackson

很多人一开始对 Jackson 的印象只是:

  • ObjectMapper
  • writeValueAsString()
  • readValue()

但实际上,Jackson 不只是"对象转 JSON"这么简单,它还可以做:

  • Java 对象和 JSON 字符串互转
  • 集合、泛型、Map 的转换
  • 日期格式处理
  • 忽略字段、重命名字段
  • 空值处理
  • 枚举处理
  • 自定义序列化和反序列化
  • 与 Spring Boot 自动集成

这篇文章会系统地把 Jackson 讲清楚。

一、什么是 Jackson

Jackson 是 Java 里一个非常流行的 JSON 处理框架,核心作用是:

  • 序列化:把 Java 对象转成 JSON
  • 反序列化:把 JSON 转成 Java 对象

比如:

java 复制代码
User user = new User("张三", 18);

可以转成:

java 复制代码
{"name":"张三","age":18}

也可以把上面的 JSON 再转回 User 对象。

二、为什么要学 Jackson

因为它在 Java 后端里出现得太频繁了:

  • Spring Boot 默认就集成了 Jackson
  • 接口返回 JSON 时底层常常就是 Jackson 在处理
  • @RequestBody@ResponseBody 的很多 JSON 映射背后也是它
  • 面试里经常会问:
    • ObjectMapper 是什么
    • @JsonIgnore 有什么用
    • 如何处理日期格式
    • 如何处理泛型集合
    • 如何自定义 JSON 字段名

所以 Jackson 不只是一个工具类,而是后端接口开发的基础能力。

三、Jackson 的核心类

学习 Jackson,先记住这几个核心类。

1. ObjectMapper

这是最核心的类,几乎所有常用操作都围绕它展开。

它可以做:

  • Java 对象转 JSON 字符串
  • JSON 字符串转 Java 对象
  • JSON 转 Map
  • JSON 转集合
  • 配置序列化和反序列化规则

示例:

java 复制代码
ObjectMapper objectMapper = new ObjectMapper();

2. JsonNode

如果你不想立刻转成某个 Java 类,也可以先把 JSON 读成树结构,再按节点读取。

适合:

  • JSON 结构不固定
  • 只想临时取某个字段
  • 动态解析

3. TypeReference

Jackson 处理泛型时非常重要。

比如:

java 复制代码
List<User>
Map<String, User>
Result<User>

这些带泛型的类型,直接用 Class 不够,需要 TypeReference

四、先引入依赖

如果你是 Maven 项目:

java 复制代码
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
</dependencies>

如果你是 Spring Boot 项目,通常已经自动带上 Jackson 了,一般不用单独加。

五、最基础的用法

1. Java 对象转 JSON

先定义一个实体类:

java 复制代码
public class User {
private String name;
private Integer age;

public User() {
}

public User(String name, Integer age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public Integer getAge() {
return age;
}

public void setName(String name) {
this.name = name;
}

public void setAge(Integer age) {
this.age = age;
}
}

然后序列化:


ObjectMapper objectMapper = new ObjectMapper();

User user = new User("张三", 18);
String json = objectMapper.writeValueAsString(user);

System.out.println(json);

输出:


{"name":"张三","age":18}

这里的 writeValueAsString() 就是:

把 Java 对象写成 JSON 字符串。

2. JSON 转 Java 对象

java 复制代码
ObjectMapper objectMapper = new ObjectMapper();

String json = "{\"name\":\"李四\",\"age\":20}";
User user = objectMapper.readValue(json, User.class);

System.out.println(user.getName());
System.out.println(user.getAge());

输出:

李四

20

这里的 readValue() 就是:

把 JSON 字符串读取成 Java 对象。

六、集合和 Map 的处理

很多初学者只会转普通对象,但项目里更常见的是:

  • List<User>
  • Map<String, Object>
  • Result<User>

1. List 转 JSON

java 复制代码
List<User> list = new ArrayList<>();
list.add(new User("张三", 18));
list.add(new User("李四", 20));

ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(list);

System.out.println(json);

输出:

{"name":"张三","age":18},{"name":"李四","age":20}

2. JSON 转 List

这个地方必须注意:
不能简单写成 List.class,否则元素会变成 LinkedHashMap

正确写法:

java 复制代码
String json = "[{\"name\":\"张三\",\"age\":18},{\"name\":\"李四\",\"age\":20}]";

ObjectMapper objectMapper = new ObjectMapper();

List<User> users = objectMapper.readValue(
json,
new TypeReference<List<User>>() {}
);

for (User user : users) {
System.out.println(user.getName() + " - " + user.getAge());
}

这里的重点是:

new TypeReference<List<User>>() {}

因为 Java 泛型有类型擦除,Jackson 需要你显式告诉它完整类型。

3. JSON 转 Map

java 复制代码
String json = "{\"name\":\"张三\",\"age\":18}";

ObjectMapper objectMapper = new ObjectMapper();

Map<String, Object> map = objectMapper.readValue(
json,
new TypeReference<Map<String, Object>>() {}
);

System.out.println(map.get("name"));
System.out.println(map.get("age"));

七、常用注解详解

Jackson 之所以强大,一个重要原因就是有很多注解。

1. @JsonIgnore

忽略某个字段,不参与 JSON 序列化或反序列化。

java 复制代码
public class User {
private String name;

@JsonIgnore
private String password;

private Integer age;

// getter/setter
}

对象转 JSON 时:

{"name":"张三","age":18}

password 不会输出。

适用场景:

  • 密码
  • 敏感信息
  • 内部字段

2. @JsonProperty

给 JSON 字段改名字。

java 复制代码
public class User {
@JsonProperty("user_name")
private String name;

private Integer age;

// getter/setter
}

输出:

{"user_name":"张三","age":18}

适用场景:

  • Java 字段名和前端字段名不一致
  • 接第三方接口时字段名有特殊格式

3. @JsonFormat

常用来格式化日期。

java 复制代码
public class User {
private String name;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;

// getter/setter
}

输出:

{"name":"张三","createTime":"2025-03-08 14:30:00"}

4. @JsonInclude

控制空值字段是否输出。

java 复制代码
@JsonInclude(JsonInclude.Include.NON_NULL)
public class User {
private String name;
private Integer age;
private String email;

// getter/setter
}

如果 email = null,序列化时就不会输出 email

5. @JsonAlias

反序列化时支持别名。

java 复制代码
public class User {
@JsonAlias({"userName", "username"})
private String name;

private Integer age;

// getter/setter
}

那么这两种 JSON 都能识别:

{"userName":"张三","age":18}

{"username":"张三","age":18}


6. @JsonIgnoreProperties

忽略未知字段,防止反序列化报错。

java 复制代码
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
private String name;
private Integer age;

// getter/setter
}

如果 JSON 多了别的字段,比如:

{"name":"张三","age":18,"address":"北京"}

也不会报错。

八、空值、未知字段、日期的常见配置

这些在项目里特别常用。

1. 忽略空值字段

java 复制代码
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

这样所有 null 字段默认不输出。

2. 忽略未知字段

java 复制代码
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

当 JSON 中字段比 Java 类多时,不报错。

3. 日期格式化

java 复制代码
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));

4. 美化输出

java 复制代码
String json = objectMapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(user);

输出更好看:

{

"name" : "张三",

"age" : 18

}

适合日志、调试、学习。

九、JsonNode 的用法

如果 JSON 结构复杂,或者你只想取部分字段,可以用 JsonNode

java 复制代码
String json = "{\"name\":\"张三\",\"age\":18,\"address\":{\"city\":\"北京\"}}";

ObjectMapper objectMapper = new ObjectMapper();
JsonNode root = objectMapper.readTree(json);

String name = root.get("name").asText();
int age = root.get("age").asInt();
String city = root.get("address").get("city").asText();

System.out.println(name);
System.out.println(age);
System.out.println(city);

适用场景:

  • 第三方接口返回格式复杂
  • 字段不固定
  • 只取某几个值,不想专门建类

十、泛型对象怎么处理

很多项目都有统一返回对象,比如:

复制代码
java 复制代码
public class Result<T> {
private Integer code;
private String message;
private T data;

public Result() {
}

public Result(Integer code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}

// getter/setter
}

如果 JSON 是:

{

"code": 200,

"message": "success",

"data": {

"name": "张三",

"age": 18

}

}

要转成 Result<User>

java 复制代码
String json = "{\"code\":200,\"message\":\"success\",\"data\":{\"name\":\"张三\",\"age\":18}}";

ObjectMapper objectMapper = new ObjectMapper();

Result<User> result = objectMapper.readValue(
json,
new TypeReference<Result<User>>() {}
);

System.out.println(result.getData().getName());

这里必须使用 TypeReference<Result<User>>() {}

十一、自定义序列化器和反序列化器

当默认规则不够用时,可以自定义。

1. 自定义序列化器

比如把 Long 类型序列化成字符串,避免前端精度丢失。

java 复制代码
public class LongToStringSerializer extends JsonSerializer<Long> {
@Override
public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(String.valueOf(value));
}
}

然后在字段上使用:

java 复制代码
public class User {
@JsonSerialize(using = LongToStringSerializer.class)
private Long id;

private String name;

// getter/setter
}

这样 id 输出时就是字符串:

{"id":"1234567890123456789","name":"张三"}

2. 自定义反序列化器

比如把 "男""女" 转成数字编码。

java 复制代码
public class GenderDeserializer extends JsonDeserializer<Integer> {
@Override
public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String value = p.getText();
if ("男".equals(value)) {
return 1;
}
if ("女".equals(value)) {
return 2;
}
return 0;
}
}

字段上使用:

java 复制代码
public class User {
private String name;

@JsonDeserialize(using = GenderDeserializer.class)
private Integer gender;

// getter/setter
}

十二、枚举处理

枚举在项目里也经常用。

java 复制代码
public enum Gender {
MALE,
FEMALE
}

默认会输出枚举名:

{"gender":"MALE"}

如果你想输出更友好的值,可以配合 @JsonValue

java 复制代码
public enum Gender {
MALE("男"),
FEMALE("女");

private final String desc;

Gender(String desc) {
this.desc = desc;
}

@JsonValue
public String getDesc() {
return desc;
}
}

输出:

{"gender":"男"}

十三、Spring Boot 中 Jackson 的作用

如果你在用 Spring Boot,其实 Jackson 很多时候已经在帮你工作了。

比如:

java 复制代码
@RestController
public class UserController {

@GetMapping("/user")
public User getUser() {
return new User("张三", 18);
}

@PostMapping("/save")
public String save(@RequestBody User user) {
return "success";
}
}

这里底层发生了两件事:

1. 返回对象时

Spring Boot 会自动把 User 对象转成 JSON 返回给前端。

这个过程通常就是 Jackson 做的。

2. 接收 @RequestBody

前端传来的 JSON 会自动转成 User 对象。

这个过程也是 Jackson 做的。

所以你虽然没直接写 ObjectMapper,但你其实已经在用 Jackson。

十四、Spring Boot 中全局配置 Jackson

可以在 application.yml 中做一些简单配置:

java 复制代码
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
default-property-inclusion: non_null

作用:

  • 日期格式统一
  • 时区统一
  • 不输出 null 字段

如果要更复杂的配置,可以自己写配置类:

java 复制代码
@Configuration
public class JacksonConfig {

@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));

return objectMapper;
}
}

十五、项目中最常见的 Jackson 场景

1. 接口统一返回格式

比如你写全局返回包装:

return Result.success(body);

最后返回给前端时,Jackson 会把它转成 JSON。

2. 处理 String 特殊返回

ResponseBodyAdvice 中,如果返回的是 String,经常会手动写:

return objectMapper.writeValueAsString(Result.success(body));

因为 String 类型在 Spring 里走的是特殊转换器。

3. 日志打印对象

很多人喜欢在调试时打印对象 JSON:

System.out.println(objectMapper.writeValueAsString(user));

比直接打印对象更直观。

4. 第三方接口请求与响应

比如你调用外部接口,收到 JSON 字符串后:

Result<User> result = objectMapper.readValue(json, new TypeReference<Result<User>>() {});

十六、Jackson 常见坑

这一部分非常重要。

1. 没有无参构造器

反序列化时,Jackson 往往需要创建对象。

如果类没有无参构造器,可能会失败。

建议:

  • 实体类尽量提供无参构造器
  • 或者使用 Lombok 的 @NoArgsConstructor

2. 字段没有 getter/setter

Jackson 默认常依赖 getter/setter。

建议实体类规范写好访问器方法。

3. 泛型集合反序列化错误

错误写法:

List<User> users = objectMapper.readValue(json, List.class);

这样会得到 List<LinkedHashMap>,不是 List<User>

正确写法:

List<User> users = objectMapper.readValue(json, new TypeReference<List<User>>() {});

4. 日期格式不对

如果不配置格式,默认日期输出可能不是你想要的。

解决方式:

  • 字段上 @JsonFormat
  • 全局配置日期格式

5. Long 精度问题

前端 JavaScript 对超大整数有精度限制。

如果后端返回很大的 Long,前端可能丢精度。

解决方式:

  • Long 序列化成字符串
  • 用自定义序列化器

6. String 返回值包装问题

在 Spring 的全局响应处理中,如果遇到:

public String hello() {

return "ok";

}

直接包装成对象可能报错,需要:

objectMapper.writeValueAsString(Result.success(body))

这是 Jackson 在 Spring 项目中最常见的实战坑之一。

十七、Jackson 和 Gson 有什么区别

很多人会把 Jackson 和 Gson 放一起比较。

简单说:

Jackson

  • 性能通常不错
  • 功能强大
  • 注解丰富
  • Spring Boot 默认集成
  • 企业项目中更常见

Gson

  • API 简单
  • 上手容易
  • 小项目中也常见

如果你是做 Java 后端,尤其是 Spring Boot,

建议重点掌握 Jackson

十八、学习 Jackson 的建议路线

如果你是初学者,可以按这个顺序学:

第一阶段:核心 API

先掌握:

  • ObjectMapper
  • writeValueAsString()
  • readValue()
  • TypeReference

第二阶段:常用注解

重点学:

  • @JsonIgnore
  • @JsonProperty
  • @JsonFormat
  • @JsonInclude
  • @JsonIgnoreProperties

第三阶段:Spring Boot 集成

搞懂:

  • @RequestBody
  • @ResponseBody
  • 为什么 Controller 返回对象会自动变 JSON
  • ResponseBodyAdvice 里和 Jackson 的关系

第四阶段:进阶

学习:

  • JsonNode
  • 自定义序列化器
  • 自定义反序列化器
  • 全局 Jackson 配置
  • 枚举和日期处理

十九、实战案例:完整演示

下面给一个更贴近项目的例子。

1. 返回对象

复制代码
java 复制代码
public class Result<T> {
private Integer code;
private String message;
private T data;

public Result() {
}

public Result(Integer code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}

public static <T> Result<T> success(T data) {
return new Result<>(200, "success", data);
}

public Integer getCode() {
return code;
}

public String getMessage() {
return message;
}

public T getData() {
return data;
}

public void setCode(Integer code) {
this.code = code;
}

public void setMessage(String message) {
this.message = message;
}

public void setData(T data) {
this.data = data;
}
}

2. 用户类

复制代码
java 复制代码
@JsonInclude(JsonInclude.Include.NON_NULL)
public class User {
private Long id;

@JsonProperty("user_name")
private String name;

private Integer age;

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;

@JsonIgnore
private String password;

public User() {
}

public User(Long id, String name, Integer age, Date createTime, String password) {
this.id = id;
this.name = name;
this.age = age;
this.createTime = createTime;
this.password = password;
}

// getter/setter
}

3. 测试序列化

java 复制代码
public class JacksonDemo {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

User user = new User(1L, "张三", 18, new Date(), "123456");

String json = objectMapper.writeValueAsString(Result.success(user));
System.out.println(json);
}
}

可能输出:

{"code":200,"message":"success","data":{"id":1,"user_name":"张三","age":18,"createTime":"2025-03-08 20:30:00"}}

你会发现:

  • password 被忽略了
  • name 变成了 user_name
  • 日期格式化了
  • 外层统一包装成了 Result

这就是 Jackson 在实际项目中的典型样子。

二十、总结

Jackson 是 Java 后端开发里非常重要的基础库。

你至少要掌握这几个点:

必会

  • ObjectMapper
  • writeValueAsString()
  • readValue()
  • TypeReference

常用注解

  • @JsonIgnore
  • @JsonProperty
  • @JsonFormat
  • @JsonInclude

实战重点

  • List、Map、泛型对象的转换
  • Spring Boot 自动 JSON 映射
  • String 返回值特殊处理
  • 日期与 Long 精度问题
  • 自定义序列化和反序列化

一句话总结:

Jackson 不只是"对象转 JSON"的工具,它是 Java 后端和 JSON 世界沟通的核心桥梁。

相关推荐
灰色小旋风6 小时前
力扣合并K个升序链表C++
java·开发语言
_MyFavorite_6 小时前
JAVA重点基础、进阶知识及易错点总结(28)接口默认方法与静态方法
java·开发语言·windows
取码网6 小时前
最新在线留言板系统PHP源码
开发语言·php
环黄金线HHJX.6 小时前
龙虾钳足启发的AI集群语言交互新范式
开发语言·人工智能·算法·编辑器·交互
书到用时方恨少!6 小时前
Python Pandas 使用指南:数据分析的瑞士军刀
python·数据分析·pandas
不写八个7 小时前
PHP教程006:ThinkPHP项目入门
开发语言·php
_MyFavorite_7 小时前
JAVA重点基础、进阶知识及易错点总结(31)设计模式基础(单例、工厂)
java·开发语言·设计模式
A.A呐7 小时前
【C++第二十三章】C++11
开发语言·c++
智算菩萨7 小时前
【Pygame】第8章 文字渲染与字体系统(支持中文字体)
开发语言·python·pygame
:mnong7 小时前
全图纸语义理解升级分析
python·openvino·paddleocr·qt6.3·paddleocr-vl