Gson



Gson gson = new Gson();


// 简单类型
System.out.println(gson.toJson(1));
String str = gson.fromJson("\"abc\"", String.class);
System.out.println(str);
String[] anotherStr = gson.fromJson("[\"abc\"]", String[].class);
System.out.println(anotherStr[0]);


// 对象
BagOfPrimitives obj = new BagOfPrimitives();
String jsonStr = gson.toJson(obj);
System.out.println(jsonStr);
/*
* 注意不要序列化带有循环引用的对象,那样对导致无穷递归。
*/
BagOfPrimitives bagOfPrimitives = gson.fromJson(jsonStr,
BagOfPrimitives.class);
System.out.println("valueInt = " + bagOfPrimitives.valueInt + ","
+ "valueStr = " + bagOfPrimitives.valueStr);


/*
* gson对使用对象的细节 1. htyuan 推荐使用私有变量。 2.
* 不必使用注释来表明哪些filed应该被包含在序列化和饭序列化中。所有的在类(或超类)中的filed都默认包含。
* 3.如果某个filed被标记为transient, 默认忽略此变量,不包括在json的序列化和反序列化中。 4.正确处理了null对象
* #当序列化的时候,忽略null filed #当反序列化的时候,不会filed 对应的setting方法,让此filed是空 5.If a
* field is synthetic, it is ignored and not included in JSON
* serialization or deserialization
* 6.在内部类,匿名类,局部类中的外部类型字段在序列化和反序列化的时候被忽略掉(Fields corresponding to the
* outer classes in inner classes, anonymous classes, and local classes
* are ignored and not included in serialization or deserialization)
*/
// 嵌入类(包括内部类)
/*
* Gson可以很容易的嵌入静态内部类
* 可以反序列化内部类。可是gson不能自动反序列完全的内部类,因为他们的没有参数构造方法也需要一个包含它的类的引用,而这时候包含它的类
* 还是无效的。要解决此问题可以把内部类设置为静态的,或者或者提供一个自定义的InstanceCreator给它。例子如下

* public class A { public String a;

* class B {

* public String b;

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

* } } 注意:默认情况下B不能被反序列化。
* Gson不能反序列化{"b":"abc"}B的字段B中,因为B是一个内部类。如果B被定义为静态的就可以了。 Another
* solution is to write a custom instance creator for B

* 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(); } }
* 虽然上面的方法可以解决,但不推荐。
*/


// Array Examples
int[] ints = { 1, 2, 3, 4, 5 };
String[] strings = { "abc", "def", "ghi" };
System.out.println(gson.toJson(ints));
System.out.println(gson.toJson(strings));


int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class);
for (int i = 0; i < ints2.length; i++) {
System.out.println(ints[i]);
}
// Gson 支持包含复杂数据类型的多维数组


// Collections Examples
// 序列化
Collection<Integer> intList = new ArrayList<Integer>();
intList.add(1);
intList.add(2);
intList.add(3);
intList.add(4);
String jsonCollections = gson.toJson(ints);
System.out.println(jsonCollections);
// 反序列化
Type collectionType = new TypeToken<Collection<Integer>>() {
}.getType();
Collection<Integer> intList2 = gson.fromJson(jsonCollections,
collectionType);
for (Integer item : intList2) {
System.out.println(item);
}
/*
* Collections Limitations 可以把任意对象的集合序列化,但不能从集合中反序列化,因为用户没办法指明结果的类型。
* 当反序列化的时候Collect必须是一个指定的通用类型。
*/


// 序列化和反序列化和通用类型
/*
* 当你调用toJson(obj)进行序列化的时候,Gson调用obj.getClass()获取要序列化的字段信息。类似的,你也可以传递
* MyClass.class 对象给 fromJson(json, MyClass.class)
* 方法。如果是非通用类型,这点工作的很好。可是如果这是一个通用类型的对象,通用类型的对象信息会消失 因为java类型擦处(Java Type
* Erasure)。 下面的例子说名这一点。
class Foo<T> {
T value;
}
Gson gson = new Gson();
Foo<Bar> foo = new Foo<Bar>();
gson.toJson(foo); // 获取不会正确的序列化foo.value


gson.fromJson(json, foo.getClass()); // 反序列化 foo.value 的时候失败。
 
上面的代码在把value解释为Bar类型的时候会失败。Gson调用list.getClass()获取到的是一个被raw类。
这也就是说Gson没有办法或Foo<Bar>的类型,因为这不是一个简单的类型。
你可以使用通用类型来解决这个问题,指定通用类型的参数。你可能需要  TypeToken 类来实现。
Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
gson.toJson(foo, fooType);

gson.fromJson(json, fooType);
这种获得fooType的惯用方式实际上是定义了一个局部类,在这个类中包含了一个返回full 参数类型的方法getType()。
*/


//Serializing and Deserializing Collection with Objects of Arbitrary Types
/*
有时候你会处理包含混合类型的数组。例如 ['hello',5,{name:'GREETINGS',source:'guest'}]
匹配的集合为
*/
//Event类型的定义是
class Event {
 private String name;
 private String source;
 private Event(String name, String source) {
   this.name = name;
   this.source = source;
}

}

Collection collection = new ArrayList();
collection.add("hello");
collection.add(5);
collection.add(new Event("GREETINGS", "guest"));
/*
 你可以用Gson序列化上面的集合同时不用做任何指定: toJson(collection) 可以写处输出。
 可以用fromJson(json, Collection.class)反序列化却不行,因为Gson没有办法知道从输入到类型怎么映射。
 Gson要求应该为 fromJson提供一个通用版本类型。因此, 你有3个类型的选项。
 选项1 : 使用Gson的解析api(低级流解析或DOM解析JsonPaser)解析数组,即用Gson.fromJson()解析每一个具体的数据元素。
    这是一个优先的解决方案。这有个例子https://code.google.com/p/google-gson/source/browse/trunk/extras/src/main/java/com/google/gson/extras/examples/rawcollections/RawCollectionsExample.java
 选项2 : 注册一个Collection类型的适配器,适配器考虑数组中的每一个成员,映射它们到合适的对象【Register a type adapter for Collection.class that looks at each of the array members and maps them to appropriate objects】。
    这种方案的缺点就是在Gson中其它类型的集合的反序列化变得很糟糕。【The disadvantage of this approach is that it will screw up deserialization of other collection types in Gson】
 选项3 : 注册一个MyCollectionMemberType类型的adapter,使用Collection<MyCollectionMemberType>作为fromJson的参数。
    如果数组作为一个顶级元素或者   你可以改变filed的类型为Collection<MyCollectionMemberTyep>集合类型【
    you can change the field type holding the collection to be of type Collection<MyCollectionMemberTyep>】
    这样这个方法比较实用。
 */

//Built-in Serializers and Deserializers
/*
Gson已经为一些常用类提供了内嵌的序列化,但这些类默认的描述可能不合适。
下买是这样类的列表。
1.java.net.URL 匹配类似 "http://code.google.com/p/google-gson/".
2.java.net.URI匹配类似字符串  "/p/google-gson/"
你可以在https://sites.google.com/site/gson/gson-type-adapters-for-common-classes-1找到一些常用类的源代码,如JodaTime
*/

//Custom Serialization and Deserialization
/*
有时候默认表示不是你想要的。当处理库类的时候经常发生这样的情况(例如DateTime)
Gson允许你定义你自己的序列化和反序列化。通过定义下面的两部分完成。
Json Serialiers:需要为对象定义自定义的序列化。
Json Deserializers: 需要为一个类型定义自定义的发序列化。
Instance Creators:如果没有带参数的构造函数或没有注册反序列化器不需要实例化创建者。
 
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是用来检查类型adapter是否实现了不止一个这样的接口,并且把接口注册到了adapter.【
registerTypeAdapter call checks if the type adapter implements more than 
one of these interfaces and register it for all of them】
 
// Writing a Serializer
 下面是一个为DateTime使用自定义序列化器的例子
 private class DateTimeSerializer implements JsonSerializer<DateTime> {
 public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context) {
   return new JsonPrimitive(src.toString());
 }
 }
 
 //Writing a Deserializer
 下面是为DateTime的一个反序列化的例子
 private class DateTimeDeserializer implements JsonDeserializer<DateTime> {
 public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
     throws JsonParseException {
   return new DateTime(json.getAsJsonPrimitive().getAsString());
 }
}
 当需要反序列化一个字符串片段到一个DateTime,Gson会调用 fromJson()。
 
 //Finer points with Serializers and Deserializers
 你想要为所有更raw类型对应的通用类型注册一个handler.
 1)例如,假设你有一个用来表示Id的Id类。
 2)Id<T>对所有的通用类型都有相同的序列化。
       本质上输出一个id value.
 3) 反序列化很像,但不完全一样
        需要调用 "new Id(Class<T>, String)" which returns an instance of Id<T>    
        
 Gson支持注册一个单独的处理器为上面的情况。
 
 //Writing an Instance Creator
 当反序列化一个对象的时候,Gson需要创建一个这个类的默认实例。
 被用户序列化和反序列化的行为良好的类应该有一个无参数构造器。
 共有的或似有的都没有关系
 当有一个系统类没有一个无参的构造函数的时候。 Instance Creators的作用就凸显出来了。
  //Instance Creator Example
  private class MoneyInstanceCreator implements InstanceCreator<Money> {
 public Money createInstance(Type type) {
   return new Money("1000000", CurrencyCode.USD);
 }
}
类型应该是一个相应的通用类型
调用个具有通用指定通用类型参数的构造函数是是非常有用的。
例如,这个Id类就是那个代表这创建的类。
  //InstanceCreator for a Parameterized Type
   有时候你正在打算实例化的类型是一个参数话的类型。通常情况下没有问题,因为实例是一个可擦处的类型。
   这是一个类
   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 class 的实例必须通过实际传递过来的parameterized type才能完成创建。我们可以
利用传递过来的方法参数type来解决这个问题。type 对象是 Id<Foo> 在java中的表述,实际参数应该绑定到
Id<Foo>。Id类只有一个参数话的类型参数,T,getActualTypeArgument()会返回一个数组元素,我们使用
下标为0的元素,在数组元素中会有Foo.class。

//Null Object Support
null对象的默认行为是忽略。这样兼容更多一些的输出格式。可是,但但进行反序列化的时候,
客户端必须定义这些领域的默认值。
这是一个你怎样配置Gson实例来输出null
Gson gson = new GsonBuilder().serializeNulls().create();
NOTE: 当用json进行序列化的时候,将会添加一个JsonNull元素到JsonElement结构题中。
因此这个对象可以用来在自定义的序列化,反序列化中使用。

Here's an example:


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);

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

// Versioning Support
相同对象的多个版本可以通过@Since注释来维护。这注释可以用在类上,成员变量,和方法上。
为了利用这个功能,你必须配置Gson实例,忽略某些比当前版本大的某些版本的作用域。如果
没有设置版本特征,所有的filed都会别用来进行序列化和反序列化。

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);

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

{"newerField":"newer","newField":"new","field":"old"}
 
//JSON Field Naming Support

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值