1. 概述

在这个简短的教程中,我们将探索从 Gson 序列化中排除 Java 类及其子类的一个或多个字段的可用选项。

2. 初始设置

让我们首先定义我们的类:

@Data
@AllArgsConstructor
public class MyClass {private long id;private String name;private String other;private MySubClass subclass;
}@Data
@AllArgsConstructor
public class MySubClass {private long id;private String description;private String otherVerboseInfo;
}

为方便起见,我们用Lombok对它们进行了注释(getter、setter、构造函数的语法糖……)。

现在让我们填充它们:

MySubClass subclass = new MySubClass(42L, "the answer", "Verbose field not to serialize")
MyClass source = new MyClass(1L, "foo", "bar", subclass);

我们的目标是防止MyClass.otherMySubClass.otherVerboseInfo字段被序列化。

我们期望得到的输出是:

{"id":1,"name":"foo","subclass":{"id":42,"description":"the answer"}
}

在 Java 中:

String expectedResult = "{\"id\":1,\"name\":\"foo\",\"subclass\":{\"id\":42,\"description\":\"the answer\"}}";

3.transient 修饰符

我们可以用transient 修饰符标记一个字段:

public class MyClass {private long id;private String name;private transient String other;private MySubClass subclass;
}public class MySubClass {private long id;private String description;private transient String otherVerboseInfo;
}

Gson 序列化程序将忽略声明为transient 的每个字段:

String jsonString = new Gson().toJson(source);
assertEquals(expectedResult, jsonString);

虽然这非常快,但它也有一个严重的缺点:每个序列化工具都会考虑transient ,不仅仅是 Gson。

Transient 是 Java 从序列化中排除的方式,那么我们的字段也将被Serializable的序列化以及管理我们对象的每个库工具或框架过滤掉。

此外,transient关键字始终适用于序列化和反序列化,这可能会根据用例进行限制。

4. @Expose注解

Gson com.google.gson.annotations @Expose注释反其道而行之。

我们可以使用它来声明要序列化的字段,而忽略其他字段:

public class MyClass {@Expose private long id;@Expose private String name;private String other;@Expose private MySubClass subclass;
}public class MySubClass {@Expose private long id;@Expose private String description;private String otherVerboseInfo;
}

为此,我们需要使用 GsonBuilder 实例化 Gson:

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
String jsonString = gson.toJson(source);
assertEquals(expectedResult, jsonString);

这次我们可以在字段级别控制是否应该针对序列化、反序列化或两者(默认)进行过滤。

让我们看看如何防止MyClass.other被序列化,但允许在从 JSON 反序列化期间填充它:

@Expose(serialize = false, deserialize = true)
private String other;

虽然这是 Gson 提供的最简单的方法,并且不会影响其他库,但它可能意味着代码中的冗余。如果我们有一个类有一百个字段,而我们只想排除一个字段,我们需要写九十九个注解,这有点大材小用。

5.排除策略

一个高度可定制的解决方案是使用com.google.gson。排除策略。

它允许我们定义(外部或使用匿名内部类)一种策略来指示 GsonBuilder 是否使用自定义标准序列化字段(和/或类)。

Gson gson = new GsonBuilder().addSerializationExclusionStrategy(strategy).create();
String jsonString = gson.toJson(source);assertEquals(expectedResult, jsonString);

让我们看一些使用智能策略的例子。

5.1。使用类和字段名称

当然,我们也可以硬编码一个或多个字段/类名称:

ExclusionStrategy strategy = new ExclusionStrategy() {@Overridepublic boolean shouldSkipField(FieldAttributes field) {if (field.getDeclaringClass() == MyClass.class && field.getName().equals("other")) {return true;}if (field.getDeclaringClass() == MySubClass.class && field.getName().equals("otherVerboseInfo")) {return true;}return false;}@Overridepublic boolean shouldSkipClass(Class<?> clazz) {return false;}
};

这是快速而直接的,但不是很可重用,并且在我们重命名属性的情况下也容易出错。

5.2. 使用业务标准

由于我们只需要返回一个布尔值,因此我们可以在该方法中实现我们喜欢的每个业务逻辑。

在以下示例中,我们将以“other”开头的每个字段标识为不应序列化的字段,无论它们属于哪个类:

ExclusionStrategy strategy = new ExclusionStrategy() {@Overridepublic boolean shouldSkipClass(Class<?> clazz) {return false;}@Overridepublic boolean shouldSkipField(FieldAttributes field) {return field.getName().startsWith("other");}
};

5.3. 使用自定义注释

另一种聪明的方法是创建一个自定义注释:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Exclude {}

然后我们可以利用ExclusionStrategy以使其与@Expose注释完全一样工作,但相反:

public class MyClass {private long id;private String name;@Exclude private String other;private MySubClass subclass;
}public class MySubClass {private long id;private String description;@Exclude private String otherVerboseInfo;
}

这是策略:

ExclusionStrategy strategy = new ExclusionStrategy() {@Overridepublic boolean shouldSkipClass(Class<?> clazz) {return false;}@Overridepublic boolean shouldSkipField(FieldAttributes field) {return field.getAnnotation(Exclude.class) != null;}
};

这个 StackOverflow 答案首先描述了这种技术。

它允许我们编写一次注解和策略,并且无需进一步修改就可以动态地注解我们的字段。

5.4. 将排除策略扩展到反序列化

无论我们将使用哪种策略,我们总是可以控制它应该应用在哪里。

仅在序列化期间:

Gson gson = new GsonBuilder().addSerializationExclusionStrategy(strategy)

仅在反序列化期间:

Gson gson = new GsonBuilder().addDeserializationExclusionStrategy(strategy)

总是:

Gson gson = new GsonBuilder().setExclusionStrategies(strategy);

6. 结论

我们已经看到了在 Gson 序列化期间从类及其子类中排除字段的不同方法。

我们还探讨了每种解决方案的主要优势和缺陷。

与往常一样,完整的源代码可在 Github 上获得。

从 Gson 中的序列化中排除字段相关推荐

  1. GSON使用笔记(1) -- 序列化时排除字段的几种方式

    http://blog.csdn.net/zxhoo/article/details/21471005 GSON是Google发布的JSON序列化/反序列化工具,非常容易使用.本文简要讨论在使用GSO ...

  2. fastjson中@JSONType的使用-排除字段

    @JSONType(includes = {""}) 以后,通过下面的方式这个类的属性就不会转化到jsonObject中了. JSONObject jsonObject = (JS ...

  3. Gson:如何从没有注释的序列化中排除特定字段

    我正在尝试学习Gson,并且在领域排除方面苦苦挣扎. 这是我的课 public class Student { private Long id;private String firstName = & ...

  4. Gson解析JSON数据中动态未知字段key的方法

    转载自:https://blog.csdn.net/jdsjlzx/article/details/76785239 有时在解析json数据中的字段key是动态可变的时候,由于Gson是使用静态注解的 ...

  5. 2.3系列系统中不支持SimpleDateFormat作字段被序列化

    安卓问题记录:在2.3系列系统中不支持SimpleDateFormat作字段被序列化,使用时需要将SimpleDateFormat作临时变量使用. 转载于:https://www.cnblogs.co ...

  6. java中的序列化和反序列化

    一.序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存 ...

  7. 谈谈:.Net中的序列化和反序列化

    序列化和反序列化相信大家都经常听到,也都会用, 然而有些人可能不知道:.net为什么要有这个东西以及.net Frameword如何为我们实现这样的机制, 在这里我也是简单谈谈我对序列化和反序列化的一 ...

  8. java中序列化与反序列化_Java中的序列化

    java中序列化与反序列化 Java提供了一种称为序列化的机制,以按字节的有序或字节序列的形式持久化Java对象,其中包括对象的数据以及有关对象的类型和存储在对象中的数据类型的信息. 因此,如果我们已 ...

  9. java 序列化实例_Java中的序列化与反序列化实例

    创建的字节流与平台无关.因此,在一个平台上序列化的对象可以在另一个平台上反序列化. 为了使Java对象可序列化,我们实现java.io.Serializable可序列化接口. ObjectOutput ...

最新文章

  1. Atitit 实现java的linq 以及与stream api的比较
  2. ollections 模块之OrderedDict
  3. Intel Sandy Bridge/Ivy Bridge架构/微架构/流水线 (7) - 流水线前端/译码后指令缓存
  4. xml和html是兄弟还是父子?
  5. linux java环境变量修改不生效_ansible执行带有环境变量的脚本不生效
  6. popToRootViewController & popToViewController
  7. (十四)三次样条插值
  8. WPF 嵌入字体文件
  9. 【Word】批量修改Word 图片大小
  10. 以太坊生态缺陷导致的一起亿级代币盗窃大案
  11. Databricks:打造数据国度的“金砖四国”
  12. 超值得入手的无线蓝牙耳机,四款性价比最高的蓝牙耳机品牌推荐
  13. 解决Chrome flash过期
  14. matlab怎么标记节点,为图节点和边添加标签
  15. 详解智能制造中的计算机视觉应用瓶颈问题
  16. 微信小程序-从零开始制作一个跑步微信小程序 1
  17. 天气预报文字版微信_早起微信励志语录 微信群里的带励志语录的天气预报在哪找...
  18. SpringCloud学习笔记-基本组件介绍
  19. SMART目标定义原则
  20. 杭州薰衣草庄园以及停车场

热门文章

  1. 《高效程序员的45个习惯——敏捷开发修炼之道》读书笔记
  2. 海量数据成功举办openGauss Developer Day 2022“数据库内核探秘”专场论坛
  3. 检验一个数据集是否是正太分布
  4. 参考文献缺少geebinf modified by zz格式解决方法
  5. AutoHotkey循环切换Win10或则Win11任务视图的多个虚拟桌面(切换桌面)
  6. 《拉勾Java高薪课程》阶段一输出 之 通过房屋租赁流程理解设计模式(单例模式,代理模式,工厂模式)--菜鸟小回
  7. 小米手机查看/data/data/等文件的方法
  8. Unity音乐播放完整案例
  9. 2019年人工智能的薪资前景如何?程序员如何学习人工智能?
  10. vux使用方法 php,如何使用vux-ui自定义表单验证