Gson使用规则

基本规范

  • 推荐使用 private 类型,支持使用 final 声明
  • 支持 null 值,序列化输出时自动跳过,反序列化时直接返回null
  • 支持多维数组、Collection类型
  • 支持 URL、URI 的反序列化自动类型转换(也可支持JodaTime转换,参考 JodaTime Type Converter)
  • 不需要定义 getter / setter 方法(通过反射设置参数值)
  • 不需要带参构造函数,并且无参构造函数不必为 public
  • 不必要使用注解标记序列化对象,除非需要指定别名映射
  • 当前类及其所有父类的所有字段均视为默认序列化对象
  • 序列化、反序列化(如 Collection 等)泛型类型时,需要通过 TypeToken 指定目标泛型的确切类型值
  • 反序列化 混合类型数组 时,可参考官方指引:Serializing and Deserializing Collection with Objects of Arbitrary Types

不属于序列化输出范围

  • transient 类型字段
  • 非 static 嵌套类、内部类型
  • 经非序列化方式指定的字段

指定Json字段命名映射

Gson 默认使用类字段名作为序列化、反序列化的 Json 数据字段名。
可通过 @SerializedName(name) 注解指定该字段对应的 Json 字段名,也可以通过添加字段命名内置策略方式改变字段名输出形式。
通过实现 FieldNamingStrategy 接口,可自定义命名映射策略,通过 gsonBuilder.setFieldNamingStrategy(FieldNamingStrategy) 方式进行设定。

// 添加 @SerializedName 注解指定命名
// 可分别通过 value 和 alternate数组 指定序列化、反序列化时有效的字段命名
private class SomeObject {
  @SerializedName("custom_naming") private final String someField;
  private final String someOtherField;
}

// 添加名字映射策略,这里使用首字母大写驼峰策略
Gson gson = new GsonBuilder()
    .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
    .create();

通过 TypeToken 指定泛型类型值

Foo foo = new Foo();

// 指定泛型的确切类型值
Type fooType = new TypeToken>(){}.getType();

// 泛型序列化、反序列化,传入泛型类型值(序列化过程可不传入,但不保证序列化结果正确性)
gson.toJson(foo, fooType);
gson.fromJson(json, fooType);

Collection类型在序列化时受Gson内部支持,不需要指定泛型类型。

通过 TypeAdapter 彻底自定义序列化、反序列化行为

通过自定义实现 TypeAdapterJsonSerializer / JsonDeserializer 接口,指定Json的序列化、反序列化完整逻辑。

其中 TypeAdapter 为低层抽象类,自定义实现从流开始完全接管、控制序列化行为,序列化对象为 JsonWriter / JsonReader,运行效率而言相对较高。

JsonSerializer / JsonDeserializer 可按需分别指定特定类型值的序列化、反序列化的过程,序列化对象为 JsonElement

当目标对象类型不提供无参构造函数时,需要注册一个 InstanceCreator 实现类,用于以无参方式实例化一个目标对象。

  • (可选)实现 InstanceCreator 接口,提供以无参方式构造一个默认只能带参构造的目标容器对象
  • (可选)实现 JsonSerializer 接口,提供目标对象序列化至JsonElement类型的方法
  • (可选)实现 JsonDeserializer 接口,提供JsonElement类型反序列化至目标类型的方法
  • (可选)派生 TypeAdapter 子类,提供基于流的序列化、反序列化完整逻辑
GsonBuilder builder = new GsonBuilder();

// 需要时注册一个自定义 InstanceCreator 对象
builder.registerTypeAdapter(MyType.class, new MyInstanceCreator());

// 通过 registerTypeAdapter() 方法指定一个针对特定类型对象的委托序列化、反序列化器
// 第一个class类型参数必须为具体包装类型,可指定为一个泛型
// 使用 registerTypeHierarchyAdapter 则可使用抽象父类作为类型值,但不支持泛型
builder.registerTypeAdapter(String.class, new MySerializer());
builder.registerTypeAdapter(Integer.class, new MyDeserializer());

// 通过派生 TypeAdapter 指定一个针对特定类型对象的委托序列化、反序列化器
// 如果派生的 TypeAdapter 不对null参数值进行特殊处理
// 可简单使用 new MyTypeAdapter().nullSafe() 代替
builder.registerTypeAdapter(MyType2.class, new MyTypeAdapter());

Gson gson = builder.create();

注册使用 JsonSerializerJsonDeserializerTypeAdapterTypeAdapterFactory 等自定义序列化处理器时,对于同一目标类型的(反)序列化以最后一个注册为准。
Gson的处理优先顺序为 registerTypeAdapter() > 注解 > 内置TypeAdapter ,在注册指定序列化处理器时,Gson注解等内置自动序列化系统将失效(控制权由自定义处理器掌控)。

参考:
  • Custom Serialization and Deserialization
  • TypeAdapter -

关于 null 的支持

默认状态下,null 值的对象在序列化 Json 过程中会直接忽略,不输出到 Json 结果,但可通过以下方式简单的启用 null 输出:gsonBuilder.serializeNulls().create()

反序列化时,传入空的Json或null或"null",将直接返回null

输出 Json 效果如:

gson.toJson(stuff) -> {"name":null,"number":5}
gson.toJson(null) -> null

gson.fromJson("", Type.class) -> null

序列化版本支持

可指定某些字段仅在特定版本下实施序列化,比序列化所用 Gson 对象指定版本更高的字段将被忽略。

public class VersionedClass {

  // 通过 @Since 和 @Until 注解指定该字段的有效起始版本(包含)、有效到期版本(不包含)
  @Since(1.1) private final String newerField;

  @Since(1.0) private final String newField;

  @Until(2.0) private final String oldField;

  private final String field;
}

// 指定 1.0 版本时,序列化输出 Json 不包括 1.1 版本及以上的字段 newerField
// 但包含 2.0 版本以下时可用的字段 oldField
Gson gson = new GsonBuilder().setVersion(1.0).create();
...

// 不指定版本时,版本机制无效,所有字段都将输出到结果 Json
gson = new Gson();
...

使用内置的方案筛选非序列化字段

默认状态下Gson自动排除经 transient 声明的字段。
除此之外,可在 GsonBuilder 中通过以下两种方式添加额外的排除方案:

// 通过 excludeFieldsWithModifiers 指定需要排除的修饰符
Gson gson = new GsonBuilder()
    .excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)
    .create();


// 通过 @Expose 注解标记可以序列化的合法字段
// 其中可选分别指定 serialize 和 deserialize 的有效性
// @Expose = @Expose(serialize = true, deserialize = true)
@Expose private final String fieldForOutput;
final String fieldForCacheLocally;

gson = new GsonBuilder()
    .excludeFieldsWithoutExposeAnnotation()
    .create();

使用自定义方案识别非序列化字段

派生 ExclusionStrategy 子类,覆盖指定方法,以代码逻辑方式判断需要排除的字段类型、注解标记、字段值等特征。

Gson gson = new GsonBuilder()
    .setExclusionStrategies(new MyExclusionStrategy(String.class))
    .addSerializationExclusionStrategy(ExclusionStrategy)
    .addDeserializationExclusionStrategy(ExclusionStrategy)
    .create();
参考:
  • User Defined Exclusion Strategies
  • ExclusionStrategy Docs

其他可选格式化设置

通过 GsonBuilder 可链式设置多种格式化方案:

  • serializeNulls():允许序列化输出 null
  • setDateFormat("yyyy-MM-dd"):设置序列化、反序列化时使用的日期格式
  • disableInnerClassSerialization():禁止序列化内部类
  • generateNonExecutableJson():生成JS中不可执行的 Json(在前缀插入一些特殊字符)
  • disableHtmlEscaping():禁用Html自动转义
  • setPrettyPrinting():以可读格式输出,默认序列化Json不包含空格,使用可读格式输出时将激活内置的JsonPrintFormatter,生成添加额外空格缩进排版的Json字符串(格式不可自定义)
  • serializeSpecialFloatingPointValues():允许序列化特殊浮点标记值,如 NAN、Infinity、-Infinity
  • enableComplexMapKeySerialization():允许序列化复合型key(如一个自定义对象等)

其他文献参考

你真的会用Gson吗?Gson使用指南

你可能感兴趣的:(Gson使用规则)