Gson|忽略指定字段

导论

直接看代码,项目采用 JPA ORM,在实现一对多关联的时候,需要这样设置PO

假设一个任务对应多个任务节点

任务实体TaskConfig:

1
2
3
4
@JsonIgnoreProperties(value = {"taskPO"})
@OneToMany(mappedBy = "taskPO", fetch = FetchType.LAZY, cascade = {CascadeType.ALL}, orphanRemoval = true)
private List<TaskNodeConfig> nodeConfigList;

任务节点实体TaskNodeConfig

1
2
3
@ManyToOne(targetEntity = TaskConfig.class, fetch = FetchType.LAZY)
@JoinColumn(name = "task_config_code", referencedColumnName = "code", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
private TaskConfig taskPO;

上面的@JoinColumn(name = "task_config_code", referencedColumnName = "code" 用于指定我们任务节点实体表中的task_config_code字段对应任务实体表中的code字段作关联

这样定义才可以实现关联,但是在序列化任务实体对象的时候存在问题:

任务实体对象有nodeConfigList字段,nodeConfigList字段中每一个元素又都有各自的taskPO字段;taskPO字段中又有nodeConfigList字典,因此如果不在序列化的时候忽略taskPO字段,则会子子孙孙无穷匮也

忽略字段实现

GOSN中提供了三种方式来实现字段的忽略:

  • transient关键字
  • @Expose注解指定哪些字段【要】序列化
  • 实例化Gson对象时指定策略

三种方式各有具体的使用场景以及限制,下面展开描述

transient关键字

对于想要忽略的字段使用 transient 关键字进行修饰

但是在上面的例子中并不适用,因为要忽略的 taskPO 字段是需要给 JPA 作为关联表关联键的,如果设置为 transient 修饰,启动会报 JPA 的错,说 field not found

@Expose

这种方式是忽略的反方向,指定哪些字段要序列化

但是此处我们只想忽略这一个字段,如果对象中剩下的字段较多,这种方式也不合适

顺带一提,如果选择使用@Expose的方式,在序列化的时候应该调用像下面这样的GSON实例的toJSONString函数

1
2
3
4
5
6
7
8
9
10
private static final Gson gsonExclude = getExcludeGsonBuilder().create();

private static GsonBuilder getExcludeGsonBuilder() {
return new GsonBuilder()
.setDateFormat("yyyy-MM-dd HH:mm:ss")
.disableInnerClassSerialization()
//开启expose功能
.excludeFieldsWithoutExposeAnnotation()
.disableHtmlEscaping();
}

自定义排除策略

我们新建一个自定义注解

1
2
3
4
5
6
7
import java.lang.annotation.*;

@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IgnoreGsonField {
}

将注解打在想要忽略的字段上,例如之前的任务节点类

1
2
3
4
@IgnoreGsonField //自定义注解
@ManyToOne(targetEntity = TaskConfig.class, fetch = FetchType.LAZY)
@JoinColumn(name = "task_config_code", referencedColumnName = "code", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
private TaskConfig taskPO;

在实例化GSON对象的时候,实现ExclusionStrategy来指定排除策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static final Gson gsonAnnotationExclude = getExcludeAnnotationGsonBuilder().create();

private static GsonBuilder getExcludeAnnotationGsonBuilder() {
return new GsonBuilder()
.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
return fieldAttributes.getAnnotation(IgnoreGsonField.class) != null;
}

@Override
public boolean shouldSkipClass(Class<?> clazz) {
return clazz.isAnnotationPresent(IgnoreGsonField.class);
}
})
.serializeNulls()
.setDateFormat("yyyy-MM-dd HH:mm:ss")
.disableInnerClassSerialization()
.disableHtmlEscaping();
}

总结

如果只希望在序列化和反序列化的时候暴露指定字段,使用@Expose并结合GsonBuilder.excludeFieldsWithoutExposeAnnotation()实例化支持Expose注解的GSON实例使用

如果希望忽略个别字段(如本文场景),可以使用自定义注解,结合GsonBuilder.setExclusionStrategies()实例化排除指定注解修饰字段的GSON实例使用


Gson|忽略指定字段
http://example.com/2025/08/13/Gson-忽略指定字段/
作者
Noctis64
发布于
2025年8月13日
许可协议