轉載請註明本文出自maplejaw的博客(http://blog.csdn.net/maplejaw_)
開源庫地址: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 {
@Expose
private 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();
所有的方法如下:
![image_1amm2a5vkurd1t6ku4412do8om9.png-45.5kB]()
-
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對象。
![image_1amn76ilalcs2usk3t1mjddmm9.png-55.7kB]()
最後
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實在太多就不進行分析了。