这篇文章部分实例来自Gson官方用户指导和API,如果有不对的地方,还请各位读者指出。
1.作用:序列化的时候,实现Java对象到Json字符串和Json字符串到Java对象的转变。
2.创建Gson的两种方式:
new Gson()创建的实例采用默认的配置,如果需要自己配置,则使用GsonBuilder
Gson gson1 = new Gson();
//or 官方API上的示例代码
Gson gson2 = new GsonBuilder()
//不包括实体值没有@Expose注解的属性,下面会详细介绍注解
.excludeFieldsWithoutExposeAnnotation()
.registerTypeAdapter(Id.class, new IdTypeAdapter())
.enableComplexMapKeySerialization()
//配置Gson序列化空字段
.serializeNulls()
.setDateFormat(DateFormat.LONG)
//序列化后字段首字母大写(使用@SerializedName无效)
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
//对Json输出更好的格式化
.setPrettyPrinting()
//配置Gson启用版本支持
.setVersion(1.0)
.create();
下面一句句进行解释,其余的部分请读者自行阅读官方API
.registerTypeAdapter(Id.class, new IdTypeAdapter())
.enableComplexMapKeySerialization()
这两句往往一起,设置了TypeAdapter就可以传进去复杂的属性作为map的key,比如Point {“(5,6):”a”},但是没有设置的话,就会被序列化为一个Json数组嵌套数组
setDateFormat(DateFormat.LONG)
这里可以穿进去两个参数,dateStyle timeStyle
DateFormat.LONG表示yyyy年M月dd日 可以自行设定为”yyyy-MM-dd HH:mm:ss.SSS’Z’”
3.详解序列化和反序列化(采用官方guide的例子)
①序列化 核心代码:gson.toJson(obj)
- 基本数据类型
Gson gson = new Gson();
gson.toJson(1); // ==> 1
gson.toJson("abcd"); // ==> "abcd"
gson.toJson(new Long(10)); // ==> 10
int[] values = { 1 }; // ==> [1]
gson.toJson(values);
- 对象
class BagOfPrimitives {
private int value1 = 1;
private String value2 = "abc";
private transient int value3 = 3;
BagOfPrimitives() {
//无参构造函数
}
}
// Serialization
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);
// ==> json is {"value1":1,"value2":"abc"}
- 数组
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"]
- 集合
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]
②反序列化 核心代码:gson.fromJson(JsonString,Class of type)
- 基本数据类型
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);
- 对象
class BagOfPrimitives {
private int value1 = 1;
private String value2 = "abc";
private transient int value3 = 3;
BagOfPrimitives() {
//无参构造函数
}
}
(Deserialization)
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
//==> obj2 is just like obj
- 数组
Gson gson = new Gson();
int[] ints = {1, 2, 3, 4, 5};
String[] strings = {"abc", "def", "ghi"};
// Deserialization
int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class);
// ==> ints2 will be same as ints
- 集合
Gson gson = new Gson();
Collection<Integer> ints = Lists.immutableList(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
4.特点
①.序列化时,空字段跳过输出;反序列化时,Json里面缺少的字段对象里面设置为null
②.反序列化静态内部类的时候会出现问题,反序列化是Json->对象,在反序列内部类的时候,由于内部类默认持有外部类的引用,但是此时外部类还不存在。解决方法:A.设置为静态内部类 B.提供一个传统的InstanceCreator(虽然可行,但是不被推荐)
下面这段代码应设置B为静态的
public class A {
public String a;
class B {
public String b;
public B() {
//B的无参构造函数
}
}
}
③.能序列化Conllection,不能反序列化它,由于没有指定生成对象的类型
④泛型,反序列化的时候,不能得到泛型的类型,只能得到简单的类型,这时使用TypeToken可以获得完全参数类型,这就是为什么要使用TypeToken的原因
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
Type fooType = new TypeToken<Foo<Bar>>() {}.getType();
gson.toJson(foo, fooType);
gson.fromJson(json, fooType);
4.注解
@Expose
在使用new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()创建Gson对象的时候(直接new Gson()的时候没有这种情况),只有@Expose的对象才会被序列化,serialize和deserialize两个值默认为true,如果为false,解释如下
//不会被序列化
@Expose(serialize = false) private String name;
//不会被反序列化
@Expose(deserialize = false)private String id;
@SerialzedName
定义属性序列化后的名称
@Expose
@SerialzedName
private String name;
transient
不序列化某个属性
private transient String name;
- 实例
Java对象:
public class Item {
@Expose @SerializedName("item_id") private int itemId;
@Expose(serialize = false) @SerializedName("item_name") private String itemName;
@SerializedName("nick_name_list") private List<String> nickNameList;
public Item(int itemId, String itemName) {
this.itemId = itemId;
this.itemName = itemName;
}
public int getItemId() {
return itemId;
}
public void setItemId(int itemId) {
this.itemId = itemId;
}
public List<String> getNickNameList() {
return nickNameList;
}
public void setNickNameList(List<String> nickNameList) {
this.nickNameList = nickNameList;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
@Override public String toString() {
return "Item{" +
"itemId=" + itemId +
", itemName='" + itemName + '\'' +
", nickNameList=" + nickNameList +
'}';
}
}
下面对上面的代码进行说明(都是通过GsonBuilder来创建Gson对象):
1.所有属性都用@SerializedName把序列化之后的对象名字重新进行了确定
2.itemId 可以同时被序列化和反序列化
itemName 不被序列化,仍然可以被反序列化
nickNameList 不能被序列化和反序列化
@Expose @SerializedName("item_id") private int itemId;
@Expose(serialize = false) @SerializedName("item_name") private String itemName;
@SerializedName("nick_name_list") private List<String> nickNameList;
MainActivity里面的测试代码:
//序列化过程
//创建item1对象
Item item1 = new Item(12,"skylineTan");
List<String> nickNameList = new ArrayList<>();
nickNameList.add("tzy");
nickNameList.add("skyline");
item1.setNickNameList(nickNameList);
//两种方式创建Gson对象
Gson gson = new Gson();
Log.d(TAG_MAIN_ACTIVITY,gson.toJson(item1));
Gson gsonBuilder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Log.d(TAG_MAIN_ACTIVITY,gsonBuilder.toJson(item1));
//反序列化过程
//得到Json字符串
String s = gson.toJson(item1);
//得到item2
Item item2 = gson.fromJson(s,Item.class);
Log.d(TAG_MAIN_ACTIVITY,item2.toString());
//得到item3
Item item3 = gsonBuilder.fromJson(s,Item.class);
Log.d(TAG_MAIN_ACTIVITY,item3.toString());
输出结果:
//序列化过程
D/MainActivity: {"item_id":12,"item_name":"skylineTan","nick_name_list":["tzy","skyline"]}
D/MainActivity: {"item_id":12}
//反序列化过程
D/MainActivity: Item{itemId=12, itemName='skylineTan', nickNameList=[tzy, skyline]}
//itemName仍然可以被反序列化,nickNameList序列化和反序列化都不行
D/MainActivity: Item{itemId=12, itemName='skylineTan', nickNameList=null}
参考文章:
Gson User Guide
Gson API