gson用户指南(下)

上篇文章gson用户指南(上)翻译到了10、序列化和反序列化有任意类型对象的collection

我们继续

11、内置的序列化器和反序列化器

Gson内置的常用的默认序列化器和反序列化器的类可能不合适。比如

java.net.URL to match it with strings like "https://github.com/google/gson/"
java.net.URI to match it with strings like "/google/gson/"

你可以从源码中找到一些常用的类。例如JodaTime 点击打开链接

12、自定义序列化和反序列化

有时候默认表示不是你想要的。通常情况下在处理库类(DateTime等)会遇到这种情况。Gson允许注册你的自定义的序列化器和反序列化器。主要需要定义两个部分:

Json序列化器:自定义对象的序列化

Json反序列化器:为一个类型自定义反序列化

实例化构造器:需要一个无参数构造方法,或者注册一个反序列化器

GsonBuilder gson = new GsonBuilder();
gson.registerTypeAdapter(MyType2.class, new MyTypeAdapter());
gson.registerTypeAdapter(MyType.class, new MySerializer());
gson.registerTypeAdapter(MyType.class, new MyDeserializer());
gson.registerTypeAdapter(MyType.class, new MyInstanceCreator());

registerTypeAdapter调用检查类型适配器实现一个以上的接口,注册它。

13、写一个序列化器

JodaTime DateTime 类的示例

private class DateTimeSerializer implements JsonSerializer<DateTime> {
  public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context) {
    return new JsonPrimitive(src.toString());
  }
}

当它运行到一个DateTime对象序列化时。Gson会调用serialize()。

14、写一个反序列化器

JodaTime DateTime 类的示例

private class DateTimeDeserializer implements JsonDeserializer<DateTime> {
  public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException {
    return new DateTime(json.getAsJsonPrimitive().getAsString());
  }
}

当需要一个JSON字符串反序列化

为DateTime对象时,Gson会调用deserialize 方法。

序列化与反序列化的细节

通常你想为所有泛型类型对应的原始类型注册一个handler

例如,假如你有一个Id类来表示id

Id类型有相同的序列化泛型类型,本质上是输出Id的值

反序列化相似但是不同,需要调用new Id(Class<T>, String) 来创建实例

Gson支持注册一个handler。你也可以为一个特定的泛型类型(比如Id < RequiresSpecialHandling >需要特殊处理)注册一个特殊的handler。toJson的类型参数()和fromJson()包含泛型类型信息来帮助你编写一个为所有泛型类型对应相同原始类型的handler。

15、编写实例创建者

当反序列化一个对象的时候,Gson需要创建类的默认对象,一个正常序列化和反序列化的类需要有无参构造方法。

无论是public的还是private的都可以

通常,在处理一个没有无参构造方法的库中的类的时候才需要实例创建器。

示例

private class MoneyInstanceCreator implements InstanceCreator<Money> {
  public Money createInstance(Type type) {
    return new Money("1000000", CurrencyCode.USD);
  }
}

Type
可以是相应的泛型

调用构造函数需要特定的泛型类型信息

16、InstanceCreator参数化类型

有时你试图实例化的类型是参数化的类型。一般来说,这不会是一个问题,因为有实际的原始类型的实例。这是一个例子:

class MyList<T> extends ArrayList<T> {
}

class MyListInstanceCreator implements InstanceCreator<MyList<?>> {
    @SuppressWarnings("unchecked")
  public MyList<?> createInstance(Type type) {
    // No need to use a parameterized list since the actual instance will have the raw type anyway.
    return new MyList();
  }
}

然而,有时你需要根据实际参数化类型创建实例。这种情况下,可以使用传递到createInstance方法的类型参数,例如

public class Id<T> {
  private final Class<T> classOfId;
  private final long value;
  public Id(Class<T> classOfId, long value) {
    this.classOfId = classOfId;
    this.value = value;
  }
}

class IdInstanceCreator implements InstanceCreator<Id<?>> {
  public Id<?> createInstance(Type type) {
    Type[] typeParameters = ((ParameterizedType)type).getActualTypeArguments();
    Type idType = typeParameters[0]; // Id has only one parameterized type T
    return Id.get((Class)idType, 0L);
  }
}

在上面的示例中,如果没有传递参数化类型的真实类型,不能创建Id类的实例。我们通过方法参数传递类型type来解决这个问题。在本例中Java对象是类型参数化的类型表示的Id
< Foo >应该绑定到实例Id < Foo >。由于Id类只有一个参数化的类型参数T,我们使用getActualTypeArgument()返回的第0个元素类型的数组将持有Foo.class

17、紧凑输出和格式化输出Json对比

默认json输出是紧凑格式,这意味着json结构中没有空格。名称和值,对象字段和对象数组中的JSON输出不会有空白字段。

null字段将在输出中被忽略(注意:null值仍将包含在集合/数组对象中)。

如果要使用格式化输出,需要在用GsonBuilder构建Gson时配置。JsonFormatter 不是公有的,外部不能直接调用。到目前为止,内部只有JsonPrintFormatter
一个格式化输出,默认一行80个字符,2个字符缩进,4个字符的右间距

示例

Gson gson = new GsonBuilder().setPrettyPrinting().create();
String jsonOutput = gson.toJson(someObject);

18、对Null对象的支持

Gson默认情况下 null对象字段会被忽略。这样允许一个更紧凑的输出格式;然而客户端必须为这些字段定义一个默认值将JSON格式转换回Java形式。

这是使Gson支持null对象输出的方法

Gson gson = new GsonBuilder().serializeNulls().create();

注意,当使用Gson序列化null对象时,会在JsonElement 结构中增加JsonNull ,这个对象不能用于自定义序列化反序列化

示例

public class Foo {
  private final String s;
  private final int i;

  public Foo() {
    this(null, 5);
  }

  public Foo(String s, int i) {
    this.s = s;
    this.i = i;
  }
}

Gson gson = new GsonBuilder().serializeNulls().create();
Foo foo = new Foo();
String json = gson.toJson(foo);
System.out.println(json);

json = gson.toJson(null);
System.out.println(json);

输出

{"s":null,"i":5}
null

19、版本支持

同一对象的多个版本可以使用@Since注解。这个注解可用于类、字段和未来的方法中。利用这一特性,可以配置Gson实例忽略当大于一些版本号的任何字段/对象。如果没有设置版本Gson实例就会进行序列化和反序列化所有字段和类。

public class VersionedClass {
  @Since(1.1) private final String newerField;
  @Since(1.0) private final String newField;
  private final String field;

  public VersionedClass() {
    this.newerField = "newer";
    this.newField = "new";
    this.field = "old";
  }
}

VersionedClass versionedObject = new VersionedClass();
Gson gson = new GsonBuilder().setVersion(1.0).create();
String jsonOutput = gson.toJson(someObject);
System.out.println(jsonOutput);
System.out.println();

gson = new Gson();
jsonOutput = gson.toJson(someObject);
System.out.println(jsonOutput);

输出

{"newField":"new","field":"old"}

{"newerField":"newer","newField":"new","field":"old"}

20、排除序列化和反序列化字段

Gson支持众多不包括顶级类、字段和字段类型机制。以下是灵活的机制,允许将字段和类排除在外。如果没有一个机制满足您的需求然后你可以使用自定义序列化器和反序列化器。

java关键字

默认情况下,如果一个字段标记为瞬态,它将被排除在外。,如果字段标记为静态,那么在默认情况下将被排除在外。如果你想包括一些字段你可以这样

import java.lang.reflect.Modifier;
Gson gson = new GsonBuilder()
    .excludeFieldsWithModifiers(Modifier.STATIC)
    .create();

可以添加多个常量

Gson gson = new GsonBuilder()
    .excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)
    .create();

21、Gson的@Expose注解

这个特性提供了一种方法,可以标记某些字段的对象排除序列化和反序列化为JSON。使用这个注解,必须调用new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()。这样@Expose注解的类和字段才能被序列化和反序列化。

22、自定义排除策略

如果排除字段和类类型上述机制不适合你,那么你可以编写自己的排斥战略,并把它应用到GSON。详细信息请参照文档,文档地址ExclusionStragegy

示例

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Foo {
  // Field tag only annotation
}

public class SampleObjectForTest {
  @Foo private final int annotatedField;
  private final String stringField;
  private final long longField;
  private final Class<?> clazzField;

  public SampleObjectForTest() {
    annotatedField = 5;
    stringField = "someDefaultValue";
    longField = 1234;
  }
}

public class MyExclusionStrategy implements ExclusionStrategy {
  private final Class<?> typeToSkip;

  private MyExclusionStrategy(Class<?> typeToSkip) {
    this.typeToSkip = typeToSkip;
  }

  public boolean shouldSkipClass(Class<?> clazz) {
    return (clazz == typeToSkip);
  }

  public boolean shouldSkipField(FieldAttributes f) {
    return f.getAnnotation(Foo.class) != null;
  }
}

public static void main(String[] args) {
  Gson gson = new GsonBuilder()
      .setExclusionStrategies(new MyExclusionStrategy(String.class))
      .serializeNulls()
      .create();
  SampleObjectForTest src = new SampleObjectForTest();
  String json = gson.toJson(src);
  System.out.println(json);
}

输出

{"longField":1234}

23、对Json字段命名的支持

Gson支持一些预先定义的字段命名策略转换标准的Java字段名,例如小写字母开头的驼峰式命名,详细信息可以参考文档FieldNamingPolicy

它也有一个基于注解的策略,允许客户端自定义名称。请注意,基于策略的注解有字段名的验证,如果一个无效的字段名称作为注解将增加运行异常。

下面是一个自定义命名策略的例子

private class SomeObject {
  @SerializedName("custom_naming") private final String someField;
  private final String someOtherField;

  public SomeObject(String a, String b) {
    this.someField = a;
    this.someOtherField = b;
  }
}

SomeObject someObject = new SomeObject("first", "second");
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
String jsonRepresentation = gson.toJson(someObject);
System.out.println(jsonRepresentation);

输出

{"custom_naming":"first","SomeOtherField":"second"}

相关地址

http://groups.google.com/group/google-gson/browse_thread/thread/cb441a2d717f6892

http://google.github.io/gson/apidocs/com/google/gson/annotations/SerializedName.html

24、共享序列化和反序列化状态

有时候需要共享序列化反序列化,可以用下面三个方法

(1)通过静态字段存储共享状态

(2)在父类中定义序列化反序列化内部类,并使用父类型的实例字段来存储共享状态。

(3)使用ThreadLocal

1,2是线程不安全的,3是线程安全的

25、流的处理

除了Gson的对象模型和数据绑定,可使用GSON读取和写入流。也可以流和对象模型的访问都是用,以获得最佳的方法。

七、Gson的设计

见GSON设计文档,对设计GSON时我们面临的问题进行了探讨。也包括GSON与可用于JSON的转换其他Java库的比较。

参考地址https://sites.google.com/site/gson/gson-design-document

八、未来Gson的增强功能

建议的改进的最新列表,或者如果你想建议更新的内容,请参照地址https://github.com/google/gson/issues

终于译完了,有点绕。

gson是非常不错的json解析框架。使用上比较简单,功能强大,效率上也不错。

欢迎扫描二维码,关注公众号

时间: 2024-11-11 10:06:03

gson用户指南(下)的相关文章

Gson 用户指南

Gson 用户指南 文档中涉及到的例子:https://github.com/ByrsH/Gson-User-Guide-zh_CN/tree/master/Example 概述 Gson 是一个能够用于转换 Java 对象到JSON表达式的 Java库.它当然也可以用于转换一个 JSON 字符串到等价的 Java 对象. Gson 能够处理任意的 Java对象,包括你没有源代码的现有对象. Gson的目标 提供简单的使用方式,例如 toString() 和 构造器(工厂方法)用于Java 和

Android官方技术文档翻译——Gradle 插件用户指南(4)

近期赶项目,白天基本没时间,仅仅有晚上在家的时候才干看一看.昨天晚上仅仅翻译完了第四章,今天就仅仅发第四章吧. 本文译自Android官方技术文档<Gradle Plugin User Guide>,原文地址:http://tools.android.com/tech-docs/new-build-system/user-guide. 翻译不易.转载请注明CSDN博客上的出处: http://blog.csdn.net/maosidiaoxian/article/details/4195580

你真的会用Gson吗?Gson使用指南(4)

原文出处: 怪盗kidou 注:此系列基于Gson 2.4. 本次文章的主要内容: TypeAdapter JsonSerializer与JsonDeserializer TypeAdapterFactory @JsonAdapter注解 TypeAdapter与 JsonSerializer.JsonDeserializer对比 TypeAdapter实例 结语 后期预告 一.TypeAdapter TypeAdapter 是Gson自2.0(源码注释上说的是2.1)开始版本提供的一个抽象类,

Gradle用户指南(章10:Web应用程序快速入门)

Gradle用户指南(章10:Web应用程序快速入门) 本章正在完善中..... 本章介绍gradle对web应用程序的支持.Gradle为web应用程序开发提供了两个插件:War插件和Jetty插件.War插件扩展了java插件并且能为你的项目构建一个war包.Jetty插件扩展了War插件并且提供了发布你的web项目到Jetty容器中的功能. 构建一个War文件 构建War文件,你需要在项目中添加War插件. 注意:你可以在gradle发布库和源文件的samples/webApplicati

你真的会用Gson吗?Gson使用指南(2)

注:此系列基于Gson 2.4. 上一篇文章 你真的会用Gson吗?Gson使用指南(1) 我们了解了Gson的基础用法,这次我们继续深入了解Gson的使用方法. 本次的主要内容: Gson的流式反序列化 Gson的流式序列化 使用GsonBuilder导出null值.格式化输出.日期时间及其它小功能 一.Gson的流式反序列化 自动方式 Gson提供了fromJson()和toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化.同时每个方法都提供了重载方法,我常用的

【Flume NG用户指南】(2)构造

作者:周邦涛(Timen) Email:[email protected] 转载请注明出处:  http://blog.csdn.net/zhoubangtao/article/details/28277575 上一篇请參考[Flume NG用户指南](1)设置 3. 配置 前边的文章已经介绍过了,Flume Agent配置是从一个具有分层属性的Java属性文件格式的文件里读取的. 3.1 定义数据流 要在一个Flume Agent中定义数据流,你须要通过一个Channel将Source和Sin

【Flume NG用户指南】(2)配置

作者:周邦涛(Timen) Email:[email protected] 转载请注明出处:  http://blog.csdn.net/zhoubangtao/article/details/28277575 上一篇请参考[Flume NG用户指南](1)设置 3. 配置 前边的文章已经介绍过了,Flume Agent配置是从一个具有分层属性的Java属性文件格式的文件中读取的. 3.1 定义数据流 要在一个Flume Agent中定义数据流,你需要通过一个Channel将Source和Sin

Gradle用户指南(章9:Groovy快速入门)

Gradle用户指南(章9:Groovy快速入门) 你可以使用groovy插件来构建groovy项目.这个插件继承了java插件的功能,且扩展了groovy编译.你的项目可以包含groovy代码.java代码或者两者混合.在其他方面,groovy项目与java项目是一致的,就像我们在章7:java快速入门中所看到的那样. 一个简单的groovy项目 让我们来看一个示例.使用groovy插件,需要添加下面的代码得到你的构建文件中. 注意:示例代码在gradle发布的源文件包的路径samples/g

阿里云 EDAS-HSF 用户指南

阿里云 EDAS-HSF 用户指南 针对 EDAS v2.3.0©Alibaba EDAS 项目组2015/8/19 1 前言本文档旨在描述阿里云 EDAS 产品中应用服务化模块的基本概念,以及如何使用. 2 产品背景 HSF(High Speed Framework)是一个高可用.高性能.分布式的服务框架.HSF 可以被看作是人体的血管,帮助应用轻松实现服务化解耦,是阿里内部各个系统通信的基础软件. 3 专业术语?  Agent安装于用于 ECS,负责 EDAS 控制台与用户 ECS 之间的通