@JsonIgnore,@JsonProperty, @JsonInclude,@JsonFormat

参考示例
需要引入

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;

功能互补:
@JsonIgnore是完全忽略某个字段,
@JsonProperty是显式指定字段的序列化/反序列化名称

经常成对出现:在实体类中,这两个注解经常被一起讨论和使用
命名相似性:都有 “Property” 这个词,容易让人联想到它们是一组相关注解

public class User {
    @JsonIgnore          // 完全忽略这个字段,不参与JSON序列化/反序列化
    private String password;
    
    @JsonProperty("user_name")  // 序列化时使用 "user_name" 而不是 "userName"
    private String userName;
    
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) // 只允许反序列化,不允许序列化
    private String email;
}

@JsonIgnoreProperties
关系:@JsonIgnoreProperties是类级别的注解,@JsonIgnore是字段级别的
用途:@JsonIgnoreProperties({“field1”, “field2”})可以忽略多个字段

@JsonInclude
关系:控制字段在什么情况下才被包含在JSON中
对比:@JsonIgnore是完全排除,@JsonInclude是条件性包含

@Transient(JPA注解)
混淆点:很多人会把 JPA 的 @Transient和 Jackson 的 @JsonIgnore搞混
区别:@Transient表示数据库忽略该字段,@JsonIgnore表示JSON序列化忽略该字段

这是 @Transient最核心的用途。当使用 JPA(如 Hibernate)操作数据库时,它会将实体类的字段与数据库表的列进行映射。如果你有一些字段不需要存储到数据库,只是用于在业务逻辑中临时计算或展示,就需要用到 @Transient。

import javax.persistence.Transient; // JPA 标准
// 或者
import org.hibernate.annotations.Transient; // Hibernate 扩展(功能类似)

告诉 JPA/Hibernate:“这个字段是临时的,请不要为它创建数据库列,在插入和更新时也请忽略它。”

import javax.persistence.*;
import lombok.Data;

@Entity
@Table(name = "sys_user")
@Data
public class SysUser {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long userId;
    
    private String userName;
    
    private String nickName;
    
    // ... 其他数据库字段 (email, phonenumber, etc.)
    
    /**
     * 临时字段:全名
     * 这个字段不会映射到数据库的 'sys_user' 表中
     * 我们只是在内存中用它来拼接 userName 和 nickName
     */
    @Transient
    private String fullName;
    
    // 一个用于业务逻辑的方法
    public String getFullName() {
        if (this.fullName == null) {
            // 如果 fullName 为空,则动态拼接
            return this.userName + "(" + this.nickName + ")";
        }
        return this.fullName;
    }
}

在这个例子中:

数据库表 sys_user不会有 full_name这一列。

当你执行 userRepository.save(user)时,fullName的值不会被存入数据库。

当你从数据库查询出一个 SysUser对象时,fullName字段会是 null(除非你在查询后手动调用 getFullName()方法为其赋值)

@Entity
@Table(name = "sys_user")
@Data
public class SysUser {
    
    @Id
    private Long userId;
    
    private String userName;
    
    // 1. 密码字段:需要存在数据库中,但不应通过API返回给前端
    private String password;
    
    // 2. 临时计算字段:不应存入数据库,但可能需要返回给前端
    @Transient
    private String displayName;
    
    // 3. 敏感且临时的字段:既不存数据库,也不返回给前端
    @Transient
    @JsonIgnore
    private String tempSecretKey; 

    // Getter 方法,用于业务逻辑
    public String getDisplayName() {
        return this.nickName + " (" + this.userName + ")";
    }
}

password: 会被存入数据库,但通过 API 返回时会被 @JsonIgnore过滤掉。

displayName: 不会被存入数据库(因为有 @Transient),但可以被序列化为 JSON 返回给前端(因为没有 @JsonIgnore)。

tempSecretKey: 既不会被存入数据库(因为有 @Transient),也不会出现在任何 API 的 JSON 中(因为有 @JsonIgnore)。

@JsonInclude

这是 Jackson 库中的一个注解,用于控制 JSON 序列化时哪些字段应该包含在输出中。

控制序列化时忽略空值或空集合字段,使 JSON 输出更简洁。

public enum Include {
    ALWAYS,                    // 总是包含(默认)
    NON_NULL,                  // 不为 null 时包含
    NON_ABSENT,                // 不为 null 或 Optional.absent 时
    NON_EMPTY,                 // 不为空时(最常用)
    NON_DEFAULT,               // 不是默认值时
    CUSTOM,                    // 自定义规则
    USE_DEFAULTS               // 使用默认设置
}
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;

@Data
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class User {
    private Long id;
    private String name;
    private String email;
    private List<String> hobbies = new ArrayList<>();
    private Map<String, Object> attributes = new HashMap<>();
    private String emptyString = "";
    private Integer zeroValue = 0;
    private Boolean falseValue = false;
    private int[] emptyArray = new int[0];
}

// 测试
User user = new User();
user.setId(1L);
user.setName(null);  // null
user.setEmail("");   // 空字符串
user.setHobbies(new ArrayList<>());  // 空列表

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(user);

// 输出结果:
// {"id":1}  // 只有 id 被序列化
// name=null, email="", hobbies=[] 等都被忽略

类级别

@JsonInclude(JsonInclude.Include.NON_EMPTY)
@Data
public class ApiResponse<T> {
    private boolean success;
    private String code;
    private String message;
    private T data;
    private List<String> errors = new ArrayList<>();
    
    // 返回结果会很干净
}

// 成功时
ApiResponse<User> success = ApiResponse.success(user);
// 输出:{"success":true,"code":"200","data":{...}}

// 失败时(无错误详情)
ApiResponse<Void> error = ApiResponse.error("系统错误");
// 输出:{"success":false,"code":"500","message":"系统错误"}
// errors=[] 被忽略

字段级别

@Data
public class ProductDetail {
    private Long id;
    private String name;
    
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    private String description;  // 只有这个字段应用 NON_EMPTY
    
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private List<String> tags;  // 这个字段用 NON_NULL
    
    private BigDecimal price = BigDecimal.ZERO;  // 默认规则
}

@JsonFormat

这是 Jackson 库中用于控制日期时间序列化和反序列化格式的注解。

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

@Data
public class User {
    private Long id;
    private String name;
    
    // 序列化格式:yyyy-MM-dd HH:mm:ss
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date birthday;
    
    @JsonFormat(pattern = "HH:mm:ss")
    private Date alarmTime;
}

还有些东西

@JsonIgnore  // 不接收,也不返回
private String field;

@JsonIgnore  // 写在getter上接收,但不返回
public String getField()

@JsonIgnore // 写在setter上不接收,但返回
public void setField()

Lombok 注意事项
@Data
public class User {
    @Getter(onMethod_ = @JsonIgnore)  // 只在getter上
    @Setter
    private String password;
}

还可以用 @JsonProperty 只接受,但不返回
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;


AUTO, 自动检测(默认,根据 getter/setter 的存在决定
READ_ONLY, // 只读, 不能反序列化(接收), 只能序列化(返回),
WRITE_ONLY, // 只写,只能反序列化(接收),不能序列化(返回)
READ_WRITE // 读写,既可序列化也可反序列化

@JsonProperty(
value = "field_name",
access = Access.WRITE_ONLY,
required = true,
index = 1)

value: 别名
access: 读写能力
required: 是否必填
index: 顺序
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值