开源库地址:https://github.com/google/gson
解读版本:2.7
Gson是一个可以用来将Java对象转换为JSON字符串的Java库。当然,它也可以把JSON字符串转换为等价的Java对象。网上已经有了不少可将Java对象转换成JSON的开源项目。但是,大多数都要求你在Java类中加入注解,如果你无法修改源码的话就比较坑爹了,此外大多数开源库并没有对泛型提供完全的支持。于是,Gson在这两个重要的设计目标下诞生了。Gson可以作用于任意的Java对象(包括接触不到源码的),与此同时还加入了完整的泛型支持。
基本用法
Gson gson = new Gson();gson.toJson(1); gson.toJson("abcd"); gson.toJson(new Long(10)); int[] values = { 1 };gson.toJson(values); 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);
public class User { public String name="maplejaw"; public int age=18; public User(){ }} User obj = new User(); Gson gson = new Gson(); String json = gson.toJson(obj); User obj2 = gson.fromJson(json, User.class);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
Type type= new TypeToken<List<User>>(){}.getType();List<User> list = gson.fromJson(json, type);
Gson gson=new GsonBuilder() .setLenient() .setPrettyPrinting() .setVersion(..) ... .create();
Gson的基本用法如上所示,使用起来比较简便,一般情况下也已经够用了。需要注意的是,Java对象一定要有一个无参构造方法,这是Gson实例化对象的关键(自定义实例后面介绍)。此外,Java对象中并不要求有set/get方法。一般只要了解以上基本用法就能够应付绝大多数情况了,如果想深入了解一些高级用法,请继续往下阅读源码解读。
源码解读
Gson中的5个注解
@Expose
表示某个成员变量暴露于JSON序列化/反序列化。只需在GsonBuilder中配置excludeFieldsWithoutExposeAnnotation()
时才会生效。当配置过后,只有使用了@Expose
注解的成员变量才会参与序列化/反序列化工作。
public class User {@Exposeprivate String firstName;@Expose(serialize = false) private String lastName;@Expose (serialize = false, deserialize = false) private String emailAddress; private String password;}
@SerializedName
表示某个成员变量序列化/反序列化的名字,无需在GsonBuilder中配置就能生效,甚至会覆盖掉FieldNamingPolicy
。
public class MyClass {@SerializedName("name") String a;@SerializedName(value="name1", alternate={"name2", "name3"}) String b;String c;public MyClass(String a, String b, String c) { this.a = a; this.b = b; this.c = c;}}
当使用了该注解后,此时序列化/反序列化的情况如下:
MyClass target = new MyClass("v1", "v2", "v3");Gson gson = new Gson();String json = gson.toJson(target);{"name":"v1","name1":"v2","c":"v3"}{"name":"v1","name1":"v2","c":"v3"}{"name":"v1","name2":"v2","c":"v3"}{"name":"v1","name3":"v2","c":"v3"}
这个注解有什么好处呢?众所周知,在Java中的变量命名规则须遵守驼峰原则,但是,如果后台使用的是PHP等其他语言,将导致命名规则不一致;又或者因为其他原因导致多条json只有一个字段不一致,总不能建立多个实体类吧?这时候这个注解就派上用场了。
@Since
表示某个成员变量从哪个版本开始生效,只在GsonBuilder中配置了setVersion()
时才会生效。
public class User {private String firstName;private String lastName;@Since(1.0) private String emailAddress; @Since(1.0) private String password;@Since(1.1) private Address address;}
@Until
表示某个成员变量从哪个版本开始失效,只在GsonBuilder中配置了setVersion()
时才会生效。
public class User { private String firstName; private String lastName; @Until(1.1) private String emailAddress; @Until(1.1) private String password; }
@JsonAdapter
表示在某一个成员变量或者类上使用TypeAdapter。至于TypeAdapter是什么东东,后面介绍。举个例子:
假如有个User类如此下:
public class User { public final String firstName, lastName; private User(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; }}
准备编写一个UserJsonAdapter。
public class UserJsonAdapter extends TypeAdapter<User> {@Override public void write(JsonWriter out, User user) throws IOException { out.beginObject(); out.name("name"); out.value(user.firstName + " " + user.lastName); out.endObject();}@Override public User read(JsonReader in) throws IOException { in.beginObject(); in.nextName(); String[] nameParts = in.nextString().split(" "); in.endObject(); return new User(nameParts[0], nameParts[1]);}}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
将UserJsonAdapter应用到属性:此时,Gadget中的User,将会按照UserJsonAdapter来进行序列化/反序列化
private static final class Gadget {@JsonAdapter(UserJsonAdapter.class)public User user;}
将UserJsonAdapter应用到类:此时,在序列化/反序列User对象时,都会按照UserJsonAdapter来执行。
@JsonAdapter(UserJsonAdapter.class) public class User { public final String firstName, lastName; private User(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; }}
JsonReader/JsonWriter
在Gson中,Java对象与JSON字符串之间的转换是通过字符流来进行操作的。JsonReader继承于Reader用来读取字符,JsonWriter继承于Writer用来写入字符。
假如,现在有如下一段JSON数据用来表示一个用户列表。name
为名字,age
为年龄,geo
为定位的经纬度。如何使用JsonReader转为java对象?
首先查看一下json的结构,不难发现最外层是一个数组。于是,我们定义出如下readJsonStream
从Stream(流)中读取用户列表,读取完毕后,务必记得关闭流。
public List<User> readJsonStream(InputStream in) throws IOException { JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8")); try { return readUserArray(reader); } finally { reader.close(); } } public List<User> readUserArray(JsonReader reader) throws IOException { List<User> users = new ArrayList<User>(); reader.beginArray(); while (reader.hasNext()) { users.add(readUser(reader)); } reader.endArray(); return users; } public User readUser(JsonReader reader) throws IOException { String name = null; int age = -1; List<Double> geo=null; reader.beginObject(); while (reader.hasNext()) { String name = reader.nextName(); if (name.equals("name")) { name = reader.nextString(); } else if (name.equals("age")) { age = reader.nextInt(); } else if (name.equals("geo")&& reader.peek() != JsonToken.NULL) { geo = readDoublesArray(reader); } else { reader.skipValue(); } } reader.endObject(); return new User(name, age,geo); } public List<Double> readDoublesArray(JsonReader reader) throws IOException { List<Double> doubles = new ArrayList<Double>(); reader.beginArray(); while (reader.hasNext()) { doubles.add(reader.nextDouble()); } reader.endArray(); return doubles; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
我们不难发现如下规律,每次读取数组或者对象之前,都必须调用beginObject()
或者beginArray()
,读完相应内容后,也必须调用endObject()
或者endArray()
。reader.hasNext()
用来判断是否还有下一个元素,然后调用nextName
来取下一个属性名,以及一系列的nextXXX
来取相应的值。
上面介绍的是将json字符串转换为java对象的用法,现在来看看如何使用JsonWriter来讲java对象转为json字符串。
public void writeJsonStream(OutputStream out, List<User> users) throws IOException { JsonWriter writer = new JsonWriter(new OutputStreamWriter(out, "UTF-8")); writer.setIndent(" "); writeUsersArray(writer, users); writer.close(); } public void writeUsersArray(JsonWriter writer, List<User> users) throws IOException { writer.beginArray(); for (User user : users) { writeUser(writer, user); } writer.endArray(); } public void writeUser(JsonWriter writer, User user) throws IOException { writer.beginObject(); writer.name("name").value(user.getName()); writer.name("age").value(user.getAge()); if (user.getGeo() != null) { writer.name("geo"); writeDoublesArray(writer, user.getGeo()); } else { writer.name("geo").nullValue(); } writer.endObject(); } public void writeDoublesArray(JsonWriter writer, List<Double> doubles) throws IOException { writer.beginArray(); for (Double value : doubles) { writer.value(value); } writer.endArray(); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
JsonWriter用来写入JSON字符串的规则和JsonWriter大相径庭,每次写入数组或者对象之前,都必须调用beginObject()
或者beginArray()
,写完相应内容后,也必须调用endObject()
或者endArray()
。name(xx)
用来写入名字,value(XX)
用来写入值。
接下来,深入浅出解析源码!stream包的结构如下:
枚举类JsonToken
的源码如下,主要用于表示JSON字符串中的名字/值的结构。
public enum JsonToken { BEGIN_ARRAY, END_ARRAY, BEGIN_OBJECT, END_OBJECT, NAME, STRING, NUMBER, BOOLEAN, NULL, END_DOCUMENT }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
JsonScope是一个常量类,元素词法作用域。用来标识JsonReader/JsonWriter现在读/写到哪了。
final class JsonScope { static final int EMPTY_ARRAY = 1; static final int NONEMPTY_ARRAY = 2; static final int EMPTY_OBJECT = 3; static final int DANGLING_NAME = 4; static final int NONEMPTY_OBJECT = 5; static final int EMPTY_DOCUMENT = 6; static final int NONEMPTY_DOCUMENT = 7; static final int CLOSED = 8;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
JsonWriter
JsonWriter,用于将Java对象写为JSON字符串。使用前我们可以进行一些默认的配置:
public final void setIndent(String indent) //设置宽松的容错性(顶级值可以不是为object/array,数字可以为无穷) public final void setLenient(boolean lenient) //html转义 public final void setHtmlSafe(boolean htmlSafe) //序列化空,默认true public final void setSerializeNulls(boolean serializeNulls)
JsonWriter使用一个数组来保存当前的写入状态(就是标识写到哪了),JsonScope中已经介绍过了。
private int[] stack = new int[32]; private int stackSize = 0; { push(EMPTY_DOCUMENT); }
注意stack并没有定死32的长度,当写满时将会扩大一倍。使用push
来保存当前写入状态,peek
查看当前状态。
private void push(int newTop) { if (stackSize == stack.length) { int[] newStack = new int[stackSize * 2]; System.arraycopy(stack, 0, newStack, 0, stackSize); stack = newStack; } stack[stackSize++] = newTop; } private int peek() { if (stackSize == 0) { throw new IllegalStateException("JsonWriter is closed."); } return stack[stackSize - 1]; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
在写一个对象之前,必须使用beginObject()
。一定很好奇beginObject()
做了什么,当时还不忙着看,先来看看怎么写入name/value的。
name(XX)
源码如下:
public JsonWriter name(String name) throws IOException { if (name == null) { throw new NullPointerException("name == null"); } if (deferredName != null) { throw new IllegalStateException(); } if (stackSize == 0) { throw new IllegalStateException("JsonWriter is closed."); } deferredName = name; return this; }
看完源码不由觉得有点失望,只是赋值给了deferredName,其他什么事也没做。那么到底什么时候写入name的。这还得从写入value看起。
value(XX)
有很多重载函数。
我们只看value(String)
这种。
public JsonWriter value(String value) throws IOException { if (value == null) { return nullValue(); } writeDeferredName(); beforeValue(); string(value); return this; }
通过writeDeferredName
写入名字,beforeValue
写入:
,string
写入真正的值。当然writeDeferredName
也不是说直接写入name,而是先beforeName
进行状态校验,换行,替换状态,按需写入,
,然后使用string
写入name值。
private void writeDeferredName() throws IOException { if (deferredName != null) { beforeName(); string(deferredName); deferredName = null; } }
现在来看看beginObject
,如果该对象是name/value中的value,那么writeDeferredName用来写入name。open
写入{
以及更改栈顶状态。
public JsonWriter beginObject() throws IOException { writeDeferredName(); return open(EMPTY_OBJECT, "{"); }
endObject
则是调用close
来写入}
,传入的EMPTY_OBJECT,EMPTY_OBJECT
用来比较是在哪种状态下进行关闭的。
public JsonWriter endObject() throws IOException { return close(EMPTY_OBJECT, EMPTY_OBJECT, "}"); }
至于beginArray/endArray
的源码这里就不赘述了。
JsonReader
JsonReader,用于将JSON字符串转为Java对象。
JsonReader中的setLenient
的容错性那可是非常厉害。以下错误都能被忽略。
)]}'\n
前缀- 多个顶级值
- 顶级值不是 object/array类型
- 数字类型为无穷数,或者不是个数字
- 一行的结尾存在//或者 #注释
- C语言风格的注释/…/
- name用了单引号或者没用引号
- string用了单引号或者没用引号
- 数组元素的分隔符用了;而不是,
- name和value不是用:分隔,而是用=或=>
- name/value对之间不是逗号分隔,而是;分隔
和JsonWriter一样,也使用一个数组stack来保存当前的读取到的字符的类型和状态。其中引入了一系列的PEEKED_XX
int常量来记录读取的字符类型。由于篇幅问题,JsonReader就不深入研究了,以下列出JsonReader中的核心方法。
fillBuffer
用来读取字符到buffer
数组中nextNonWhitespace
用来读取非空格/注释/换行等字符peek()
查看元素类型,对应于JsonToken中的值。doPeek()
内部使用了nextNonWhitespace
读取一个字符,然后设置当前的读取的字符类型。hasNext
object/array中是不是还有下一个元素nextName
读取下一个namenextString/nextInt/nextBoolean/nextLong/nextDouble/nextNull
用来读取下一个对应的值。skipValue
跳过下一个valuenextQuotedValue/nextUnquotedValue
用来读取下一个单引号/双引号没有引号括起来的name或者string valuebeginObject/endObject/beginArray/endArray
用来消费下一个对应类型的字符
Gson中的泛型
在了解Gson中的泛型前,我们来看两个类,$Gson$Types和$Gson$Preconditions。
$Gson$Types,专门用来处理泛型类型。核心源码如下:
public static Type canonicalize(Type type) { if (type instanceof Class) { Class<?> c = (Class<?>) type; return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c; } else if (type instanceof ParameterizedType) { ParameterizedType p = (ParameterizedType) type; return new ParameterizedTypeImpl(p.getOwnerType(), p.getRawType(), p.getActualTypeArguments()); } else if (type instanceof GenericArrayType) { GenericArrayType g = (GenericArrayType) type; return new GenericArrayTypeImpl(g.getGenericComponentType()); } else if (type instanceof WildcardType) { WildcardType w = (WildcardType) type; return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds()); } else { return type; } } public static Class<?> getRawType(Type type) { if (type instanceof Class<?>) { return (Class<?>) type; } else if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; Type rawType = parameterizedType.getRawType(); checkArgument(rawType instanceof Class); return (Class<?>) rawType; } else if (type instanceof GenericArrayType) { Type componentType = ((GenericArrayType)type).getGenericComponentType(); return Array.newInstance(getRawType(componentType), 0).getClass(); } else if (type instanceof TypeVariable) { return Object.class; } else if (type instanceof WildcardType) { return getRawType(((WildcardType) type).getUpperBounds()[0]); } else { String className = type == null ? "null" : type.getClass().getName(); throw new IllegalArgumentException("Expected a Class, ParameterizedType, or " + "GenericArrayType, but <" + type + "> is of type " + className); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
canonicalize这个方法中返回了一系列的XXImpl,其实只是实现了java.io.Serializable接口,重写了equal方法而已。其中ParameterizedType/GenericArrayType/WildcardType,熟悉泛型的应该不会陌生,这里就不赘述了。
$Gson$Preconditions,这个类用于条件校验,源码很是简洁。
public final class $Gson$Preconditions { private $Gson$Preconditions() { throw new UnsupportedOperationException(); } public static <T> T checkNotNull(T obj) { if (obj == null) { throw new NullPointerException(); } return obj; } public static void checkArgument(boolean condition) { if (!condition) { throw new IllegalArgumentException(); } }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
现在回过来了解Gson中的泛型,Gson中用TypeToken来表示泛型。
源码如下:
public class TypeToken<T> { final Class<? super T> rawType; final Type type; final int hashCode; protected TypeToken() { this.type = getSuperclassTypeParameter(getClass()); this.rawType = (Class<? super T>) $Gson$Types.getRawType(type); this.hashCode = type.hashCode(); } public final Class<? super T> getRawType() { return rawType; } public final Type getType() { return type; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
由于Java中只能通过getGenericSuperclass
获取父类泛型类型,所以TypeToken必须new出一个子类Type type= new TypeToken<List<User>>(){}.getType();
来使用。
getSuperclassTypeParameter
的源码如下:
static Type getSuperclassTypeParameter(Class<?> subclass) { Type superclass = subclass.getGenericSuperclass(); if (superclass instanceof Class) { throw new RuntimeException("Missing type parameter."); } ParameterizedType parameterized = (ParameterizedType) superclass; return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]); }
JsonElement
JsonElement,一个抽象类,代表着JSON中的元素类型。可以表示JsonObject,JsonArray,JsonPrimitive,JsonNull。换言之,Gson中的JsonObject/JsonArray/JsonPrimitive/JsonNull继承于JsonElement。JsonElement也提供了一系列的getAsXXX
方法来获取元素。
我们着重看一下JsonPrimitive,JsonPrimitive代表着java中的基本数据类型。可以看出,通过构造方法进行赋值,然后通过getAsXX
取值。
public final class JsonPrimitive extends JsonElement { private static final Class<?>[] PRIMITIVE_TYPES = { int.class, long.class, short.class, float.class, double.class, byte.class, boolean.class, char.class, Integer.class, Long.class, Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class }; private Object value; public JsonPrimitive(Boolean bool) { setValue(bool); } public JsonPrimitive(Number number) { setValue(number); } public JsonPrimitive(String string) { setValue(string); } public JsonPrimitive(Character c) { setValue(c); } void setValue(Object primitive) { if (primitive instanceof Character) { char c = ((Character) primitive).charValue(); this.value = String.valueOf(c); } else { $Gson$Preconditions.checkArgument(primitive instanceof Number || isPrimitiveOrString(primitive)); this.value = primitive; } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
Gson中的TypeAdapter
还记得介绍注解时提到的TypeAdapter吗?TypeAdapter是一个抽象类,可以用来自定义类型转换。源码如下。
public abstract class TypeAdapter<T> { public abstract void write(JsonWriter out, T value) throws IOException; public abstract T read(JsonReader in) throws IOException; public final TypeAdapter<T> nullSafe() { return new TypeAdapter<T>() { @Override public void write(JsonWriter out, T value) throws IOException { if (value == null) { out.nullValue(); } else { TypeAdapter.this.write(out, value); } } @Override public T read(JsonReader reader) throws IOException { if (reader.peek() == JsonToken.NULL) { reader.nextNull(); return null; } return TypeAdapter.this.read(reader); } }; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
我们只需继承于TypeAdapter,实现相应方法就能实现自己的TypeAdapter,前面我们介绍了使用注解方法来使用TypeAdapter,现在来讲一下在GsonBuilder中如何使用。
Gson gson= new GsonBuilder() .registerTypeAdapter(XX.class,new XXTypeAdapter()) .create();
在GsonBuilder中使用registerTypeAdapter配置后,就不需要使用相关注解了。那么问题来了,如果GsonBuilder和注解为同一个类配置了不同的TypeAdapter会发生什么状况?我可以很负责任的告诉你,注解的优先级是最高的。
此外,我们之前在编写UserJsonAdapter时没有处理空值情况,很容易会抛出异常,那怎么办?一种是自己处理空值情况,将代码改成如下形式。
public class UserJsonAdapter extends TypeAdapter<User> {@Override public void write(JsonWriter out, User user) throws IOException {if (user == null) { out.nullValue(); retrun; } out.beginObject(); out.name("name"); out.value(user.firstName + " " + user.lastName); out.endObject();}@Override public User read(JsonReader in) throws IOException { if (reader.peek() == JsonToken.NULL) { reader.nextNull(); return null; } in.beginObject(); in.nextName(); String[] nameParts = in.nextString().split(" "); in.endObject(); return new User(nameParts[0], nameParts[1]);}}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
第二种方法,使用nullSafe
:
Gson gson= new GsonBuilder() .registerTypeAdapter(User.class,new UserJsonAdapter().nullSafe()) .create();
TypeAdapterFactory是一个创造TypeAdapter的工厂,用来创造一些相似类型的TypeAdapter。
public interface TypeAdapterFactory { <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type);}
继承TypeAdapter,需要重写write
和read
相关方法,可是只想处理序列化和反序列化中的一种该怎么办?那么接下来就该介绍JsonSerializer
和JsonDeserializer
接口了。可以在@JsonAdapter
注解和registerTypeAdapter
中注册使用。
public interface JsonSerializer<T> { public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context);}public interface JsonDeserializer<T> { public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)throws JsonParseException;}
序列化策略
LongSerializationPolicy
枚举类,指定长整型的序列化类型,默认有DEFAULT,STRING两种类型,可继承它实现其他类型
InstanceCreator 实例创造器
当反序列化时需要实例化对象,但是假如该对象没有默认构造方法怎么吧?那么就自定义自己的实例创造器。InstanceCreator一般配合ConstructorConstructor一起使用。
public interface InstanceCreator<T> {public T createInstance(Type type);}
class UserInstanceCreator implements InstanceCreator<User> {public User createInstance(Type type) { return new User(null, -1);}}
FieldNamingStrategy
提供了一个自定义的字段命名机制
public interface FieldNamingStrategy {public String translateName(Field f);}
FieldNamingPolicy
一个枚举类,实现了FieldNamingStrategy,提供了一些默认的字段命名机制,IDENTITY
:原始机制;UPPER_CAMEL_CASE
:首字母大写的驼峰映射;UPPER_CAMEL_CASE_WITH_SPACES
:用空格分隔的大写驼峰LOWER_CASE_WITH_UNDERSCORES
:下划线相连的小写映射;LOWER_CASE_WITH_DASHES
:虚线相连的小写映射。
FieldAttributes
用来存取字段的属性:getName
获取字段名,getDeclaringClass
获取声明的类,getDeclaredType
获取字段的声明类型,getAnnotation
获取注解。
ExclusionStrategy
一个用于定义排除策略的的接口。
public interface ExclusionStrategy {public boolean shouldSkipField(FieldAttributes f);public boolean shouldSkipClass(Class<?> clazz);}
其他
Excluder 排除器,主要用于根据策略和注解来判断哪些字段应该被忽略。
属性如下:
private static final double IGNORE_VERSIONS = -1.0d;public static final Excluder DEFAULT = new Excluder();private double version = IGNORE_VERSIONS;private int modifiers = Modifier.TRANSIENT | Modifier.STATIC;private boolean serializeInnerClasses = true;private boolean requireExpose;private List<ExclusionStrategy> serializationStrategies = Collections.emptyList();private List<ExclusionStrategy> deserializationStrategies = Collections.emptyList();
所有的方法如下:
Primitives 一个工具类,用于在原始类型和包装类型间转化。wrap
包装,unwrap
解开。
ObjectConstructor 一个人通用的构造器接口。
public interface ObjectConstructor<T> { public T construct();}
ConstructorConstructor 保存实例构造器集合的类
public final class ConstructorConstructor { private final Map<Type, InstanceCreator<?>> instanceCreators; public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {final Type type = typeToken.getType();final Class<? super T> rawType = typeToken.getRawType();final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);if (typeCreator != null) { return new ObjectConstructor<T>() { @Override public T construct() { return typeCreator.createInstance(type); } };}final InstanceCreator<T> rawTypeCreator = (InstanceCreator<T>) instanceCreators.get(rawType);if (rawTypeCreator != null) { return new ObjectConstructor<T>() { @Override public T construct() { return rawTypeCreator.createInstance(type); } };}ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);if (defaultConstructor != null) { return defaultConstructor;}ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType);if (defaultImplementation != null) { return defaultImplementation;}return newUnsafeAllocator(type, rawType);} }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
JsonStreamParser 解析器,解析为JsonElement。hasNext
:是否有下一个元素,next
取下一个元素,返回JsonElement。
Streams 内部使用TypeAdapters.JSON_ELEMENT
写入/读取下一个JsonElement。
GSON 源码解读
构造方法
现在我们从Gson的构造方法入手,解读Gson是如何工作的。
Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy, final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls, boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues, LongSerializationPolicy longSerializationPolicy, List<TypeAdapterFactory> typeAdapterFactories) { this.constructorConstructor = new ConstructorConstructor(instanceCreators); this.excluder = excluder; this.fieldNamingStrategy = fieldNamingStrategy; this.serializeNulls = serializeNulls; this.generateNonExecutableJson = generateNonExecutableGson; this.htmlSafe = htmlSafe; this.prettyPrinting = prettyPrinting; this.lenient = lenient; List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>(); factories.add(TypeAdapters.JSON_ELEMENT_FACTORY); factories.add(ObjectTypeAdapter.FACTORY); factories.add(excluder); factories.addAll(typeAdapterFactories); factories.add(TypeAdapters.STRING_FACTORY); factories.add(TypeAdapters.INTEGER_FACTORY); factories.add(TypeAdapters.BOOLEAN_FACTORY); factories.add(TypeAdapters.BYTE_FACTORY); factories.add(TypeAdapters.SHORT_FACTORY); TypeAdapter<Number> longAdapter = longAdapter(longSerializationPolicy); factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter)); factories.add(TypeAdapters.newFactory(double.class, Double.class, doubleAdapter(serializeSpecialFloatingPointValues))); factories.add(TypeAdapters.newFactory(float.class, Float.class, floatAdapter(serializeSpecialFloatingPointValues))); factories.add(TypeAdapters.NUMBER_FACTORY); factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY); factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY); factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter))); factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter))); factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY); factories.add(TypeAdapters.CHARACTER_FACTORY); factories.add(TypeAdapters.STRING_BUILDER_FACTORY); factories.add(TypeAdapters.STRING_BUFFER_FACTORY); factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL)); factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER)); factories.add(TypeAdapters.URL_FACTORY); factories.add(TypeAdapters.URI_FACTORY); factories.add(TypeAdapters.UUID_FACTORY); factories.add(TypeAdapters.CURRENCY_FACTORY); factories.add(TypeAdapters.LOCALE_FACTORY); factories.add(TypeAdapters.INET_ADDRESS_FACTORY); factories.add(TypeAdapters.BIT_SET_FACTORY); factories.add(DateTypeAdapter.FACTORY); factories.add(TypeAdapters.CALENDAR_FACTORY); factories.add(TimeTypeAdapter.FACTORY); factories.add(SqlDateTypeAdapter.FACTORY); factories.add(TypeAdapters.TIMESTAMP_FACTORY); factories.add(ArrayTypeAdapter.FACTORY); factories.add(TypeAdapters.CLASS_FACTORY); factories.add(new CollectionTypeAdapterFactory(constructorConstructor)); factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization)); this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor); factories.add(jsonAdapterFactory); factories.add(TypeAdapters.ENUM_FACTORY); factories.add(new ReflectiveTypeAdapterFactory( constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory)); this.factories = Collections.unmodifiableList(factories); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
构造方法让人看的眼花缭乱,尤其是往集合中加入了那么多的TypeAdapterFactory。由于是在太多无法逐一介绍。就挑个最简单的来讲解。总之明白TypeAdapter的作用即可。
ObjectTypeAdapter:内部有一个静态工厂类,所以只需ObjectTypeAdapter.FACTORY
这样调用即可。
public final class ObjectTypeAdapter extends TypeAdapter<Object> { public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { if (type.getRawType() == Object.class) { return (TypeAdapter<T>) new ObjectTypeAdapter(gson); } return null; } };
接口的实现方法如下:
@Override public Object read(JsonReader in) throws IOException { JsonToken token = in.peek(); switch (token) { case BEGIN_ARRAY: List<Object> list = new ArrayList<Object>(); in.beginArray(); while (in.hasNext()) { list.add(read(in)); } in.endArray(); return list; case BEGIN_OBJECT: Map<String, Object> map = new LinkedTreeMap<String, Object>(); in.beginObject(); while (in.hasNext()) { map.put(in.nextName(), read(in)); } in.endObject(); return map; case STRING: return in.nextString(); case NUMBER: return in.nextDouble(); case BOOLEAN: return in.nextBoolean(); case NULL: in.nextNull(); return null; default: throw new IllegalStateException(); } } @Override public void write(JsonWriter out, Object value) throws IOException { if (value == null) { out.nullValue(); return; } TypeAdapter<Object> typeAdapter = (TypeAdapter<Object>) gson.getAdapter(value.getClass()); if (typeAdapter instanceof ObjectTypeAdapter) { out.beginObject(); out.endObject(); return; } typeAdapter.write(out, value); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
关于TypeAdapter这里就不继续深究了,预定义的TypeAdapter实在太多了。其中JsonAdapterAnnotationTypeAdapterFactory
用来处理@JsonAdapter
注解,ReflectiveTypeAdapterFactory
用来反射获取字段等等。
getAdapter
将Java对象序列化为Json字符串时,需要调用gson.getAdapter(XX)
来获取相应类型的转换器,然后按照TypeAdapter中规定好的规则进行序列化/反序列化。
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) { TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type); if (cached != null) { return (TypeAdapter<T>) cached; } Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get(); boolean requiresThreadLocalCleanup = false; if (threadCalls == null) { threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>(); calls.set(threadCalls); requiresThreadLocalCleanup = true; } FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type); if (ongoingCall != null) { return ongoingCall; } try { FutureTypeAdapter<T> call = new FutureTypeAdapter<T>(); threadCalls.put(type, call); for (TypeAdapterFactory factory : factories) { TypeAdapter<T> candidate = factory.create(this, type); if (candidate != null) { call.setDelegate(candidate); typeTokenCache.put(type, candidate); return candidate; } } throw new IllegalArgumentException("GSON cannot handle " + type); } finally { threadCalls.remove(type); if (requiresThreadLocalCleanup) { calls.remove(); } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
以上源码的流程是这样的。首先从typeTokenCache
中获取看看有没有相应类型的Adapter,第一次肯定没有,然后利用中间变量FutureTypeAdapter
,从工厂中遍历去取,然后放入typeTokenCache
中。FutureTypeAdapter
是一个代理TypeAdapter,内部还是原TypeAdapter进行处理。
toJson
终于快接近尾声了,现在来看toJson
方法的内部原理,到底是怎么一步步将对象转为Json字符串的。最终调用的是toJson(Object src, Type typeOfSrc, JsonWriter writer)
方法,通过相应的Adapter进行读写。
public String toJson(Object src) { if (src == null) { return toJson(JsonNull.INSTANCE); } return toJson(src, src.getClass()); } public String toJson(Object src, Type typeOfSrc) { StringWriter writer = new StringWriter(); toJson(src, typeOfSrc, writer); return writer.toString(); }public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException { try { JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer)); toJson(src, typeOfSrc, jsonWriter); } catch (IOException e) { throw new JsonIOException(e); } } public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException { TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc)); boolean oldLenient = writer.isLenient(); writer.setLenient(true); boolean oldHtmlSafe = writer.isHtmlSafe(); writer.setHtmlSafe(htmlSafe); boolean oldSerializeNulls = writer.getSerializeNulls(); writer.setSerializeNulls(serializeNulls); try { ((TypeAdapter<Object>) adapter).write(writer, src); } catch (IOException e) { throw new JsonIOException(e); } finally { writer.setLenient(oldLenient); writer.setHtmlSafe(oldHtmlSafe); writer.setSerializeNulls(oldSerializeNulls); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
fromJson
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException { Object object = fromJson(json, (Type) classOfT); return Primitives.wrap(classOfT).cast(object); } public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException { if (json == null) { return null; } StringReader reader = new StringReader(json); T target = (T) fromJson(reader, typeOfT); return target; } public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException { JsonReader jsonReader = newJsonReader(json); T object = (T) fromJson(jsonReader, typeOfT); assertFullConsumption(object, jsonReader); return object; } public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { boolean isEmpty = true; boolean oldLenient = reader.isLenient(); reader.setLenient(true); try { reader.peek(); isEmpty = false; TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT); TypeAdapter<T> typeAdapter = getAdapter(typeToken); T object = typeAdapter.read(reader); return object; } catch (EOFException e) { } finally { reader.setLenient(oldLenient); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
GsonBuilder
GsonBuilder用来对Gson进行配置,比如注册TypeAdapter等等。最后调用create()
返回Gson对象。
最后
Gson内部的Json与Java间的转换依赖于各类的TypeAdapter,通过registerTypeAdapter可以注册新的类型转换器,实例创造器的等。越先注册的优先级就越高。当然,如果你没有注册Adapter,对于自定义的对象一般参与转换的Adapter是ReflectiveTypeAdapterFactory
。有兴趣的请自行阅读源码。
registerTypeAdapter的源码如下:
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) { $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?> || typeAdapter instanceof InstanceCreator<?> || typeAdapter instanceof TypeAdapter<?>); if (typeAdapter instanceof InstanceCreator<?>) { instanceCreators.put(type, (InstanceCreator) typeAdapter); } if (typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?>) { TypeToken<?> typeToken = TypeToken.get(type); factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter)); } if (typeAdapter instanceof TypeAdapter<?>) { factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter)); } return this; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
本期解读到此结束,由于篇幅问题,Gson中预定义的TypeAdapter实在太多就不进行分析了。