gson是一个java库,用作java对象和json表达式之间的转换。gson可以处理任何Java对象,包括已经存在的、你没有源代码的对象。gson有很多的优势,比如它强大的功能:1.反序列化25M以上的字符串没有任何问题。2.它可以序列化一个有140万个对象的集合,3.反序列话87000个对象的集合,4.gson1.4 提高了反序列化字节数组的限制,从87KB提高到了11M.此外。
在刚开始学习Gson的时候,我试图在百度上寻找资料。是的,资料很多,但都是零零散散的资料,并不是我想要的系统的学习资料。浏览了下Gson官网,看到有个Gson User Guilde,我觉得从这里切入是不错的选择,虽然我英语很烂,六级都没过,但是我发现阅读英文资料好像更容易读懂一点,貌似编程这东西用英语表示能表示的更加具体和清晰。
下载地址:点击下载gson,下载好以后把jar文件放入libs目录下,然后在android studio中,在jar文件上右键,选择add as library
json源码里面有个examples目录,这个目录下有个android的例子。这个例子界面有点丑,如下:
但是使用这个例子可以帮你省去一些时间,在使用这个工程的时候,注意,直接用android studio打开后是无法使用的,但是你可以用android studio 下的 File->New->import Project功能,它会为你生成android studio可以直接运行的项目。如果这个过程出了问题,应该是gradle的某些配置不对,如果你遇到类似的问题,可以参考下我的这两篇文章:
理解与配置android studio中的gradle
详细配置android studio中的gradle
为了使用Gson,首先需要获得Gson的一个实例,有两种方法获得它:1. new Gson(),2. GsonBuilder,使用这个类也可以创建一个Gson实例,并且你可以做一些设置,比如版本控制等等。
使用new Gson会创建一个默认参数的Gson对象,你基本不需要做什么,家乡下面这样:
Gson gson = new Gson();
如果你想做细致的控制,可以像下面这样:
Gson gson = new GsonBuilder()
.registerTypeAdapter(Id.class, new IdTypeAdapter())
.enableComplexMapKeySerialization()
.serializeNulls()
.setDateFormat(DateFormat.LONG)
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.setPrettyPrinting()
.setVersion(1.0)
.create();
Gson真的设计的非常简练,使用Gson转换java对象与json表达式貌似主要涉及两个方法,而且很多情况下这个两个方法就能搞定一切,这两个方法就是toJson()和fromJson()。
// 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);
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
注意:你不能序列化一个循环引用,这将会导致无限循环。
关于序列化与反序列化的对象的一些细节:
Gson可以轻易的序列化静态嵌套类。
Gson也可以反序列化静态嵌套类。Gson不能自动反序列化纯内部类,因为他们的无参构造函数也需要包含对象的引用,而这个引用在反序列化的时候不可用。你可以使用两种方法解决这个问题:
比如说一下例子:
public class A {
public String a;
class B {
public String b;
public B() {
// No args constructor for B
}
}
}
public class InstanceCreatorForB implements InstanceCreator {
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, 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也支持多维数组。
Gson gson = new Gson();
Collection 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>(){}.getType();
Collection ints2 = gson.fromJson(json, collectionType);
// ==> ints2 is same as ints
当我们调用toJson(obj),Gson会调用obj.getClass()来获取需要序列化的字段。同样的,我们可以传入MyClass.class对象给fromJson(json,MyClass.class),当对象不是泛型的时候,一切都工作良好,可是,如果对象是泛型,由于java类型擦除机制,泛型的信息会丢失。下面有一个解释这点的例子:
class Foo {
T value;
}
Gson gson = new Gson();
Foo foo = new Foo();
gson.toJson(foo); // May not serialize foo.value correctly
gson.fromJson(json, foo.getClass()); // Fails to deserialize foo.value as Bar
上面的代码无法过去Bar类型的值,所以会解析失败。因为Gson会调用list.getClass()获得类信息,但是这个方法返回了一个原始的值,Foo.class,也就是说我们无法知道类的类型是一个Foo你可以解决这个问题,使用指定泛型的正确的参数化类型:
Type fooType = new TypeToken>() {}.getType();
gson.toJson(foo, fooType);
gson.fromJson(json, fooType);
这里通过将要过去类型的泛型类型,传递给一个TypeToken的匿名子类的getType方法,从而获得一个完全的参数化类型。
有时候需要处理包含多种类型的json数组,比如:
{name:'GREETINGS',source:'guest'}]
与之等价的集合是这样的:
Collection collection = new ArrayList();
collection.add("hello");
collection.add(5);
collection.add(new Event("GREETINGS", "guest"));
class Event {
private String name;
private String source;
private Event(String name, String source) {
this.name = name;
this.source = source;
}
}
你可以序列化集合使用toJson(connect),这没有任何问题,可以的要期望的结果
但是,如果是使用fomJson进行反序列化的话就不能进行,因为Gson不知道怎样把输入映射为类型。所以你有三个选择解决这个问题:
Gson gson = new Gson();
Collection collection = new ArrayList();
collection.add("hello");
collection.add(5);
collection.add(new Event("GREETINGS", "guest"));
String json = gson.toJson(collection);
System.out.println("Using Gson.toJson() on a raw collection: " + json);
JsonParser parser = new JsonParser();
JsonArray array = parser.parse(json).getAsJsonArray();
String message = gson.fromJson(array.get(0), String.class);
int number = gson.fromJson(array.get(1), int.class);
Event event = gson.fromJson(array.get(2), Event.class);
System.out.printf("Using Gson.fromJson() to get: %s, %d, %s", message, number, event);
Gson User Guilde内容较多,这里就只介绍它的常规使用,其他的内容会在后续的文章中继续探究。