gson 学习笔记

1,005 阅读5分钟

gson使用学习

2017年1月11日

##gson使用

可以通过new Gson()方法来用gson对象,也可以通过GsonBuidler来创建包含各种设置的gson对象。

Gson实例在调用Json操作的时候不会保存状态,所以,可以复用同一个gson对象来处理不同的json序列化和反序列化。

1) 基本用法

Gson gson = new Gson();
gson.toJson(1);              //===> 1
gson.toJson("abcd");         //===> "abcd"
gons.toJson("new Long(10)"); //====>10
int[] values = {1};
gson.toJson(values);        //====> [1]
//反序列化
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[].calss);

注意:不能序列化被引用的对象,否则会导致无限循环

2)处理对象

对象处理的细节:

  • 最好使用private
  • 不需要用注解来添加域到序列化或者反序列化中,当前类所有的域都默认序列化或者反序列化。
  • 如果一个域被transient标记,那么这个域不会被序列化或者反序列化。
  • 需要正确的处理null。
  • 序列化的时候,null对象不会输出到json中。
  • 反序列化的时候,在设置对象的字段中如果缺少一项用null。
  • 当域是synthetic类型时,不会被序列化或者反序列化。
  • fields corresponding to the outer classes in inner classes,annonymous classes,and local classes are ignored and no included in serialization or deserialization.

嵌套类(包含内部类)

Gson可以十分简便的序列化静态内部类。

对于非静态内部类,gson是不能直接反序列化的。如果需要序列化非静态内部类,通过实现InsnceCreator接口。

public class A{
    public String a;
    class B{
        public String b;
        public B(){}
    }
}
public class InstanceCreatorForB implements InstaneCreator{
    private final A a;
    public InstanceCreatorForB(A a){
     this.a = a;
    }   
    public A.B createInstance(Type type){
      return a.new B();
    }
}

数组例子

Gson gson = new Gson();
int[] ints = {1,2,3,4};
gson.tojson(ints); //===>[1,2,3,4]
int[] ints2 = gson.fromJson("[1,2,3,4]",int[].class);

集合例子

Collection ints = List.immuableList(1,2,3,4);
String json = gson.toJson(ints);
Type type = new TypeToken>(){}.getType();
Collection ints2 = gosn.fromJson(json,type);

因为Collection对象并不能明确具体的类型,所以通过传入类型给TypeToken来获得具体反序列化的类型。

泛型

当调用toJson(obj)时,gson通过obj.getClass()来获取域的信息从而达到序列化,反序列类似。如果object不是泛型的是可以的。然而,如果object是一个泛型的话,泛型的信息是丢失的。因为gson通过getClass会获得一个原始类型。可以通过TypeToken来获得泛型的具体类型。

class Foo{
    T value;
}
Gson gson = new Gson();
Foo foo = new Foo();
gson.toJson(foo);//may not serialize foovalue correctly
gson.fromJson(json,foo.getClass());//fails to deserialize foo.value as Bar
Type fooType = new TypeToken>(){}.getType();
gson.toJson(foo,fooType); //ok
gson.fromJson(json,fooType);//ok

序列化和反序列化包含任意类型的集合

有时解析的JSON array可能包含混合类型,比如:[“hello”,5,{name:’hha’,source:’guest’}]

等价于如下Collection

Collection collection = new ArrayList();
collection.add("hello");
collection.add(5);
collection.add(new Event("hha","guest"));

通过toJson(collection)就可以序列化collection。但是不能通过fromJson(json,COllection.class)来反序列化。推荐使用下面方式来解析。

Collection collection = new ArrayList();
collection.add("hello);
collection.add(5);
collection.add(new Event("hha","guest"));
Gson gson = new Gson();
String json = gson.toJson(collection);  // 序列化
JsonParser parser = new JsonParser();
JsonArray jsonArray = parser.parser(json).getAsJsonArray();
String message = gson.fromJson(jsonArray.get(0),String.class);
int number = gson.fromJson(jsonArray.get(1),int.class);
Event event = gson.fromJson(jsonArray.get(2),Event.class);

自定义序列化器和反序列化器

Gson 允许注册自己的序列化器和反序列化器来解决一些library class(DateTime等等).如下:

  • Json Serializers: Nedd to define custom serialization for an object
  • Json Deserializers:needed to define custom deserialization for a type
  • Instance Creators: Not needed if no-args comstructor is availabe or a deserializer is registered

大概意思是需要声明自定义序列化的对象和类型。如果包含无参的构造方法或者已经注册反序列化器就不需要InstanceCreator.

Serializer

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

Gson序列化DateTime对象的时候调用serialize()方法。

Deserializer

private class DateTimeDeserializer implements JsonEdserializer{
    public DateTIme deserialize(JsonElement json ,Type typeOfT,JsonDeserializationContext contexg)
          throws JsonParseException{
        return new DateTime(jsongetAsJsonPrimitive().getAsString());
    }
}

Gson反序列化时调用deserialize。

Null对象的支持

默认情况下,为null的字段不会序列化和反序列化。可以通过serialzieNulls()来支持序列化和反序列化null的字段。

public class Event{
    private String firstField;
    private String secondField;
    public Event(String a,String b){
        this.firstField = a;
        this.secondField = b;
    }
}
Gson gson ;
gson = new Gson();
Event event = new Event("first",null);   
String json = event.toJson(event);               //====> {"firstField":"first"}
gson = new GsonBuilder().serializeNulls().create();
String json = gson.toJson(event);               //====>{"firstField":"first","secondField":null}

版本支持

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"}

JSON域命名支持

gson支持对一些域的命名策略。在FieldNamingPolicy类中。

private class SomObject{
    @SerializeName("custom_naming") private final String somfield;
    private final String somOtherfield;
    public SomeObject(String a,String b){
        this.somField = a;
        this.somOtherfield = b;
    }
}
SomeObject somObject = new SomeObject("first","second");
Gson gson = new GsonBuilder().setFieldNamingPolic(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
String jsonRepresentation = gson.toJson(somObject);  //=====> {"custom_namping":"first","SomeOtherfield","second"}

避免默写域被序列化或者反序列化

Java Modifier Exclusion

默认被transient修饰的字段不会被序列化或者反序列化。如果想让别的不被序列化,可以通过excludeFiledsWithModefiers()来实现。如下:

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

这样被static修饰的字段都不会被序列化。也可以通过excludeFieldsWithModifiers(Modifier.STATIC,Modifier.PRIVATE)。

Gson @Expose

实例gson对象的使用用GsonBuilder().excludeFiledWithoutExposeAnnotiation.create().这样
只序列化通过@Expose注解修饰的字段。

自己声明不被序列化的规则

实现ExclusionStrategy接口

public class MyExcusionStrategy implements ExclusionStrategy {
    FieldAttributes fs;
    Class clazz;
    public MyExcusionStrategy(FieldAttributes f,Class clazz) {
        this.fs = f;
        this.clazz = clazz;
    }
    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        return fs.getName().equals(f.getName());
    }
    @Override
    public boolean shouldSkipClass(Class clazz) {
        return this.clazz == clazz;
    }
}
      Money money = new Money(1, "codevalue", "exposevalue", "testvalue");
       FieldAttributes field = null;
       try {
           field = new FieldAttributes(money.getClass().getField("code"));
       } catch (NoSuchFieldException e) {
           Log.e(TAG, "onCreate: "+e.toString() );
           e.printStackTrace();
       }
       gson = new GsonBuilder()
               .setExclusionStrategies(new MyExcusionStrategy(field,
                       int.class))
               .serializeNulls()
               .create();
       String json = gson.toJson(money);
       Log.e(TAG, "onCreate: " + json);

输出结果:

{"expose":"exposevalue","test":"testvalue"}