SpringBoot使用Jackson序列化返回方式

 更新时间:2026年05月28日 09:41:54   作者:黑风风  
在SpringBoot应用中,本文详细介绍了如何使用Jackson库处理JSON的序列化和反序列化,包括自定义序列化器、使用@JsonView控制输出和处理日期及枚举类型,Jackson作为高效的JSON处理器,广泛应用于Java环境,特别是与Spring框架集成时

在Spring Boot应用中,使用Jackson库来处理JSON的序列化和反序列化是一种常见的做法。

Jackson是一个高效的JSON处理器,广泛用于Java环境中,尤其是在与Spring框架集成时。

本文将详细介绍如何在Spring Boot中配置和使用Jackson,以实现复杂对象的序列化。

基本配置

在Spring Boot项目中,默认已经集成了Jackson,因此你不需要手动引入Jackson库。

Spring Boot会自动配置Jackson,并将其用作默认的JSON转换库。

以下是一个简单的示例,展示了如何在Spring Boot应用中使用Jackson来序列化一个对象。

实体类定义

假设我们有一个名为User的实体类,包含几个属性:姓名、年龄和邮箱。

import com.fasterxml.jackson.annotation.JsonProperty;

public class User {
    private String name;
    private int age;
    private String email;

    // 标准的getter和setter
    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

控制器层

在Spring Boot控制器中,你可以直接返回一个对象,Spring MVC会自动使用Jackson将对象序列化为JSON格式。

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.setName("张三");
        user.setAge(30);
        user.setEmail("zhangsan@example.com");
        return user;
    }
}

自定义序列化,JsonSerializer

尽管Spring Boot的默认配置通常足够使用,但在某些情况下,你可能需要对Jackson的行为进行定制。以下是一些常见的自定义配置方法。

简单使用

如果你想要自定义某个类的序列化方式,可以通过实现JsonSerializer来实现。

例如,如果你想在序列化User类时隐藏邮箱信息,可以创建一个自定义的序列化器。

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;

public class UserSerializer extends StdSerializer<User> {

    public UserSerializer() {
        this(null);
    }

    public UserSerializer(Class<User> t) {
        super(t);
    }

    @Override
    public void serialize(User user, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("name", user.getName());
        jsonGenerator.writeNumberField("age", user.getAge());
        // 不序列化email字段
        jsonGenerator.writeEndObject();
    }
}

整数格式化为千分位

在使用 Jackson 进行序列化时,如果需要将整数(例如 Integer 类型)格式化为带有千分位的字符串(如 “100,000”),可以通过自定义序列化器来实现。

这里我将演示如何创建一个自定义的序列化器,并应用在一个实体类的字段上。

步骤 1: 创建自定义序列化器

首先,我们需要创建一个扩展自 JsonSerializer<T> 的类,专门用于序列化 Integer 字段。

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.text.DecimalFormat;

public class ThousandsFormatterSerializer extends JsonSerializer<Integer> {
    private static final DecimalFormat formatter = new DecimalFormat("#,###");

    @Override
    public void serialize(Integer value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (value == null) {
            gen.writeNull();
        } else {
            gen.writeString(formatter.format(value));
        }
    }
}

这个自定义的序列化器使用 DecimalFormat 将整数格式化为千分位字符串。

步骤 2: 应用注解到实体类

现在,你可以使用 @JsonSerialize 注解来指定使用这个自定义序列化器。

将此注解添加到实体类的相应字段上:

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

public class DataModel {
    private String name;

    @JsonSerialize(using = ThousandsFormatterSerializer.class)
    private Integer amount;

    // 构造函数、getter 和 setter 省略
}

在这个例子中,amount 字段将被格式化为千分位字符串,当 Jackson 序列化这个 DataModel 类的实例时。

步骤 3: 使用和测试

最后,在你的应用程序中创建 DataModel 的实例,并通过 Spring Boot 的 REST 控制器返回它,Jackson 会自动应用这个自定义的序列化器来格式化 amount 字段。

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DataController {

    @GetMapping("/formatted-data")
    public DataModel getFormattedData() {
        DataModel data = new DataModel();
        data.setName("Example");
        data.setAmount(100000);
        return data;
    }
}

当你访问这个控制器方法时,你应该会看到如下格式的 JSON 响应:

{
    "name": "Example",
    "amount": "100,000"
}

几个常用的注解

指定序列化和反序列化时JSON对象的属性名。@JsonProperty

  • 指定序列化和反序列化时JSON对象的属性名。
  • 例如,可以将Java字段名从 firstName 映射到 JSON 属性 first_name
public class User {
    @JsonProperty("first_name")
    private String firstName;
}

在序列化和反序列化过程中忽略该属性。@JsonIgnore

在序列化和反序列化过程中忽略该属性。

public class User {
    private String firstName;
    
    @JsonIgnore
    private String password;
}

用于格式化字段,如日期格式。@JsonFormat

用于格式化字段,如日期格式。

public class User {
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
    private Date birthDate;
}

下面有详细讲

使用@JsonView控制输出

@JsonView 是Jackson提供的一种方式,允许你在同一个类中定义多个视图,根据上下文来序列化不同的属性集合。

这个功能在你需要根据用户的不同权限展示不同级别的数据时特别有用。

定义视图

首先,你需要定义一些视图接口。

这些接口不包含任何方法,它们的目的是为不同的序列化视图提供标记。

public class Views {
    public static class Public {}
    public static class Internal extends Public {}
}

应用视图到实体类

然后,使用@JsonView注解来标注User实体类中的不同字段,这些字段将根据视图的不同而序列化。

public class User {
    @JsonView(Views.Public.class)
    private String name;
    
    @JsonView(Views.Public.class)
    private int age;
    
    @JsonView(Views.Internal.class)
    private String email;

    // getters 和 setters
}

控制器中使用视图

在Spring MVC控制器中,你可以通过@JsonView注解来指定哪个视图应该被用于序列化。

@RestController
public class UserController {

    @GetMapping("/user/public")
    @JsonView(Views.Public.class)
    public User getPublicUser() {
        return createUser();
    }

    @GetMapping("/user/internal")
    @JsonView(Views.Internal.class)
    public User getInternalUser() {
        return createUser();
    }

    private User createUser() {
        User user = new User();
        user.setName("张三");
        user.setAge(30);
        user.setEmail("zhangsan@example.com");
        return user;
    }
}

@JsonView和JsonSerializer混合使用

在Jackson中,@JsonViewJsonSerializer 是可以组合使用的,但这样做可能会导致一些复杂性和冗余。

这两种机制都用于控制JSON序列化的行为,但它们各自适用于不同的场景。

使用场景

  • @JsonView:这是一种较为简洁的方法,用于在不同的上下文中控制哪些属性被包含在JSON中。它适用于简单的情况,比如当同一个对象在不同的API端点返回不同字段时。
  • JsonSerializer:这是一个更为强大和灵活的工具,允许你完全控制一个对象的序列化过程。当你需要对序列化进行详细控制,如改变输出的结构或添加复杂的条件逻辑时,这是一个更好的选择。

组合使用

当你同时使用@JsonViewJsonSerializer时,通常是因为你需要处理非常具体的序列化需求,如下面的示例所示:

public class CustomUserSerializer extends StdSerializer<User> {
    public CustomUserSerializer() {
        super(User.class);
    }

    @Override
    public void serialize(User user, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        if (provider.getActiveView() != null && provider.getActiveView().equals(Views.Public.class)) {
            gen.writeStringField("name", user.getName());
        }
        if (provider.getActiveView() != null && provider.getActiveView().equals(Views.Internal.class)) {
            gen.writeStringField("email", user.getEmail());
            gen.writeNumberField("age", user.getAge());
        }
        gen.writeEndObject();
    }
}

在这个例子中,CustomUserSerializer 判断当前激活的视图,并根据视图决定序列化哪些字段。这样做虽然增加了灵活性,但也增加了代码的复杂性和维护难度。

处理日期和枚举

处理日期和枚举类型时,可能需要特别注意。Jackson提供了多种方式来定制日期和枚举的序列化方式。

日期格式化

如果你需要自定义日期的格式,可以使用@JsonFormat注解来指定日期字段的格式。

import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;

public class Event {
    private String name;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
    private Date eventDate;

    // getters 和 setters
}

枚举的自定义序列化

对于枚举类型,你可能想要序列化为不同于默认的名字。使用@JsonValue注解可以指定一个枚举的方法来返回想要序列化的值。

public enum Type {
    FULL_TIME("Full time"),
    PART_TIME("Part time");

    private String value;

    Type(String value) {
        this.value = value;
    }

    @JsonValue
    public String getValue() {
        return value;
    }
}

### 返回结果示例

假设你有一个Java类`Employee`,其中包含一个`Type`枚举字段,如下所示:

```java
public class Employee {
    private String name;
    private Type employmentType;

    public Employee(String name, Type employmentType) {
        this.name = name;
        this.employmentType = employmentType;
    }

    // Getters and Setters
}

在Spring Boot应用中,当你返回一个包含枚举字段的Employee对象时,由于Type枚举使用了@JsonValue,序列化的JSON将反映getValue()方法提供的字符串,而不是枚举的名字。

例如:

@RestController
public class EmployeeController {

    @GetMapping("/employee")
    public Employee getEmployee() {
        return new Employee("张三", Type.FULL_TIME);
    }
}

该端点返回的JSON可能如下所示:

{
    "name": "张三",
    "employmentType": "Full time"
}

这里,employmentType字段显示为"Full time",这是FULL_TIME枚举值的自定义序列化输出。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java线程中的Timer和TimerTask原理详解

    Java线程中的Timer和TimerTask原理详解

    这篇文章主要介绍了Java线程中的Timer和TimerTask原理详解,Timer和TimerTask成对出现,Timer是定时器,TimerTask是定时任务,换句话说,定时任务TimerTask是给定时器Timer执行的具体任务,需要的朋友可以参考下
    2023-10-10
  • java两个线程同时写一个文件

    java两个线程同时写一个文件

    这篇文章主要为大家详细介绍了java两个线程同时写一个文件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • IDEA启动服务提示端口被占用,Web server failed to start.Port was already in use.

    IDEA启动服务提示端口被占用,Web server failed to start.Port was al

    这篇文章主要介绍了IDEA启动服务提示端口被占用,Web server failed to start.Port was already in use.,本文给大家分享解决方案,分为linux系统和windows系统解决方案,需要的朋友可以参考下
    2023-07-07
  • springboot构造树形结构数据并查询的方法

    springboot构造树形结构数据并查询的方法

    本文主要介绍了springboot怎样构造树形结构数据并查询,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • MyBatis-Plus中使用EntityWrappe进行列表数据倒序设置方式

    MyBatis-Plus中使用EntityWrappe进行列表数据倒序设置方式

    这篇文章主要介绍了MyBatis-Plus中使用EntityWrappe进行列表数据倒序设置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • 解决SpringBoot启动报错:Failed to load property source from location 'classpath:/application.yml'问题

    解决SpringBoot启动报错:Failed to load property source from l

    这篇文章主要介绍了解决SpringBoot启动报错:Failed to load property source from location 'classpath:/application.yml'问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • Java 面向对象编程中static关键字的深度剖析与实践

    Java 面向对象编程中static关键字的深度剖析与实践

    在 Java 面向对象编程的庞大体系中, static关键字作为一项极为重要的特性,对代码的设计、组织和性能有着深远的影响,本文将深入探讨static关键字在静态变量、静态方法和工具类设计中的应用,并剖析其中的关键要点与注意事项,感兴趣的朋友跟随小编一起看看吧
    2025-09-09
  • Java杂谈之合格程序员一定要会阅读别人的源码

    Java杂谈之合格程序员一定要会阅读别人的源码

    阅读别人的代码作为开发人员是一件经常要做的事情。一个是学习新的编程语言的时候通过阅读别人的代码是一个最好的学习方法,另外是积累编程经验
    2021-09-09
  • JVM优先级线程池做任务队列的实现方法

    JVM优先级线程池做任务队列的实现方法

    这篇文章主要介绍了JVM优先级线程池做任务队列的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • Java获取文件路径的几种方式汇总

    Java获取文件路径的几种方式汇总

    本文介绍了使用Java处理文件路径的方法,包括使用java.io.File、java.nio.file.Paths类处理本地文件和类路径资源,以及在Web应用中获取路径的方法,它还提供了最佳实践和注意事项,如使用现代化的路径处理方式和跨平台兼容性,需要的朋友可以参考下
    2026-04-04

最新评论