gson用户指南(上)

一、官方地址

https://github.com/google/gson/blob/master/UserGuide.md#TOC-InstanceCreator-for-a-Parameterized-Type

api地址http://www.javadoc.io/doc/com.google.code.gson/gson/2.6.2

二、概述

gson是一个用来将JAVA对象转换成JSON串的JAVA库,它也可以用来将JSON字符串转换为Java对象。

gson可以对任意的java对象转换,包括预先存在的没有源代码java对象。

三、Gson的目标

提供易于使用的像toString()和构造函数(工厂方法)机制的Java转换成JSON,反之亦然

允许预先存在的不可修改的对象实现JSON和对象之间互转

允许自定义转换

支持任何复杂对象

生成紧凑,可读的JSON输出

四、Gson性能和可伸缩性

以下是我们在台式机(双核处理器,8GB内存,64位的Ubuntu)上获得了一些指标。您可以通过使用类PerformanceTest重新运行这些测试。
Strings: 反序列化超过25MB strings 没有发生问题(参考 PerformanceTest中的disabled_testStringDeserializationPerformance 方法 )
Large collections:
        序列化包含1400000个对象的collection (参考 PerformanceTest中的disabled_testLargeCollectionSerialization  方法)
        反序列化包含87,000个对象的colection (参考 PerformanceTest中的disabled_testLargeCollectionDeserialization 方法 )
Gson 1.4 反序列化byte数组和collection的大小从80k增加到了11MB。
注意: 运行test的时候需要删除disabled_ 前缀. 我们使用这个前缀,防止每次运行时都运行这些单元测试。

五、Gson 用户

GSON原本是为谷歌内部使用创建的,目前在许多项目中都使用的。使用的一些公共项目和公司

六、Gson的使用

1、配置

<dependencies>
    <!--  Gson: Java to Json conversion -->
    <dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
      <version>2.6.2</version>
      <scope>compile</scope>
    </dependency>
</dependencies>
// http://mvnrepository.com/artifact/com.google.code.gson/gson
compile group: 'com.google.code.gson', name: 'gson', version: '2.6.2'

2、基本数据类型转换示例

// Serialization
Gson gson = new Gson();
gson.toJson(1);            // ==> 1
gson.toJson("abcd");       // ==> "abcd"
gson.toJson(new Long(10)); // ==> 10
int[] values = { 1 };
gson.toJson(values);       // ==> [1]

// Deserialization
int one = gson.fromJson("1", int.class);
Integer one = gson.fromJson("1", Integer.class);
Long one = gson.fromJson("1", Long.class);
Boolean false = gson.fromJson("false", Boolean.class);
String str = gson.fromJson("\"abc\"", String.class);
String[] anotherStr = gson.fromJson("[\"abc\"]", String[].class);

3、对象转换示例

class BagOfPrimitives {
  private int value1 = 1;
  private String value2 = "abc";
  private transient int value3 = 3;
  BagOfPrimitives() {
    // no-args constructor
  }
}

// Serialization
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);  

// ==> json is {"value1":1,"value2":"abc"}

注意,不能序列化循环引用的对象,这将导致无限递归。


// Deserialization
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
// ==> obj2 is just like obj

4、使用细节

推荐使用private字段
没有必要使用任何注解来标注序列化和反序列化。在当前的类(和所有父类)的所有字段默认情况下都会被序列化和反序列化

如果一个字段被标记为transient,默认情况它被忽略,不包括在JSON序列化和反序列化中。
能正确处理空值

序列化过程中,输出中的空字段会被忽略

反序列化中,如果json串中缺少实体,反序列化为对象之后对应属性为null

合成字段在序列化和反序列化过程中会被忽略。

内部类,匿名类和局部类外类的字段被忽略,不会被序列化和反序列化

5、嵌套类(包括内部类)

Gson可以简单的序列化静态内部类,Gson也可以反序列化静态嵌套类。然而,GSON不能自动反序列化纯内部类,因为他们的无参数的构造还需要外部类的引用。可以通过定义静态内部类,或提供一个自定义InstanceCreator解决这个问题。下面是一个例子:


public class A { 
  public String a; 

  class B { 

    public String b; 

    public B() {
      // No args constructor for B
    }
  } 
}

注:以上的B类默认情况下不能用GSON序列化。

Gson不能将{"b":"abc"} 反序列化为B的实例,因为B类是一个普通内部类,如果将B类定义为static的,就能正常反序列化。另一种方法是自定义构建器

public class InstanceCreatorForB implements InstanceCreator<A.B> {
  private final A a;
  public InstanceCreatorForB(A a)  {
    this.a = a;
  }
  public A.B createInstance(Type type) {
    return a.new B();
  }
}
虽然能正常使用,但是不推荐用这种方式

6、数组序列化和反序列化示例


Gson gson = new Gson();
int[] ints = {1, 2, 3, 4, 5};
String[] strings = {"abc", "def", "ghi"};

// Serialization
gson.toJson(ints);     // ==> [1,2,3,4,5]
gson.toJson(strings);  // ==> ["abc", "def", "ghi"]

// Deserialization
int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class); 
// ==> ints2 will be same as ints

gson也支持任意复杂元素类型的多维数组。

7、Collections示例

Gson gson = new Gson();
Collection<Integer> ints = Lists.immutableList(1,2,3,4,5);

// Serialization
String json = gson.toJson(ints);  // ==> json is [1,2,3,4,5]

// Deserialization
Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
Collection<Integer> ints2 = gson.fromJson(json, collectionType);
// ==> ints2 is same as ints
需要特别注意,需要明确集合元素类型。不幸的是,在Java中有没有办法来解决这个问题。

8、集合上的一些限制

GSON可以序列任意对象的集合,但不能从直接反序列化,因为没有办法让用户指定生成的对象的类型。而反序列化,集合需要是泛型。遵循良好的Java编码实践时,减少问题。

9、序列化反序列化泛型

当调用toJson(obj)的时候,Gson调用obj.getClass()获取序列化属性的信息,也可以直接将对应的类传给fromJson方法,在不是泛型的时候,很实用。
如果对象是泛型,由于java类型擦除,对象的类型会丢失。

class Foo<T> {
  T value;
}
Gson gson = new Gson();
Foo<Bar> foo = new Foo<Bar>();
gson.toJson(foo); // May not serialize foo.value correctly
gson.fromJson(json, foo.getClass()); // Fails to deserialize foo.value as Bar
上面的代码将失败,因为GSON调用list.getClass()来获得它的类信息来解释值类型,但这个方法返回一个原始的类
Foo.class。这意味着,GSON没有办法知道,这是Foo<Bar>类型的具体对象,而不是简单的Foo的创建的对象。

可以通过为你的泛型类型指定正确的参数化类型解决这个问题。您可以通过使用TypeToken类做到这一点。

Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
gson.toJson(foo, fooType);

gson.fromJson(json, fooType);
获取fooType的方法实际上定义了GetType的匿名局部内部类,返回完整的参数类型。

10、序列化和反序列化有任意类型对象的collection

有时候会定义包含多种类型的Json数组,例如: ['hello',5,{name:'GREETINGS',source:'guest'}]

Collection collection = new ArrayList();
collection.add("hello");
collection.add(5);
collection.add(new Event("GREETINGS", "guest"));
Event的定义
class Event {
  private String name;
  private String source;
  private Event(String name, String source) {
    this.name = name;
    this.source = source;
  }
}
你可以简单调用toJson(collection)序列化collection,将得到想要的输出。
然而,调用fromJson(json, Collection.class)反序列化是无效的,因为Gson无法知道collection的元素类型,Gson需要明确的集合类型,你有三种选择:
(1)使用Gson解析器的API,解析数组中的每一个元素,然后在每个元素上调用 Gson.fromJson(),这是首选方法 示例

  (2)注册一个类Collection.class型的适配器,在每个数组元素上适配并将它们映射到适当的对象。这种方法的缺点是,它会破坏其他集合类型的反序列化的GSON。

(3)为MyCollectionMemberType注册用一个适配器,传入 Collection<MyCollectionMemberType>调用fromJson().这种做法实际是只有当数组元素为顶级元素才能正常,或者如果你可以改变字段类型,持有集合<MyCollectionMemberType>的类型。


先翻译到这里,剩下的内容在下篇翻译




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




你可能感兴趣的:(java,json,gson)