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