Gson 是開發中我們經常使用的一款json 解析框架,也是Google 推出的諸多良品之一,今天我們就從源碼的角度看下gson 是如何來做序列化的,即如何通過toJson方法來做序列化的。
首先是獲取Gson對象,只是Gson提供的對外方法類,有兩種方式獲取Gson對象,大概瞭解下。
GsonBuilder gsonBuilder=new GsonBuilder();
Gson BuGson=gsonBuilder.create();
Gson gson = new Gson();
序列化大概的步驟:
1.將類對象獲取適配器對象
2.通過反射機制獲取對象的方法名字段和值
3.通過流將每個字段對應的鍵和值逐個寫入拼接
4.輸出序列化後的json 字符串
因爲Gson本身有多種適配器類型,就找了一個比較有代表性的類型適配器
ReflectiveTypeAdapterFactory 類
爲了更好理解,先來個實體類,他對應的ReflectiveTypeAdapterFactory 適配器,字段中的註解暫時忽略
public class TestMode {
@Expose(deserialize = true)
private int age;
@Expose(serialize = false, deserialize = true)
String name;
@Expose(deserialize = true)
@SerializedName("len")
int length;
public TestMode(){
}
public TestMode(int age, String name, int length) {
this.age = age;
this.name = name;
this.length = length;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "TestMode{" +
"age=" + age +
", name='" + name + '\'' +
", length=" + length +
'}';
}
}
兩種初始化Gson都可以,今天就不說他倆的區別了,後邊會再出一篇具體講GsonBuilder 使用,直接看Gson 構造函數
public Gson() {
this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY,
Collections.<Type, InstanceCreator<?>>emptyMap(), DEFAULT_SERIALIZE_NULLS,
DEFAULT_COMPLEX_MAP_KEYS, DEFAULT_JSON_NON_EXECUTABLE, DEFAULT_ESCAPE_HTML,
DEFAULT_PRETTY_PRINT, DEFAULT_LENIENT, DEFAULT_SPECIALIZE_FLOAT_VALUES,
LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT, DateFormat.DEFAULT,
Collections.<TypeAdapterFactory>emptyList(), Collections.<TypeAdapterFactory>emptyList(),
Collections.<TypeAdapterFactory>emptyList());
}
Gson(Excluder excluder, FieldNamingStrategy fieldNamingStrategy,
Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
int timeStyle, List<TypeAdapterFactory> builderFactories,
List<TypeAdapterFactory> builderHierarchyFactories,
List<TypeAdapterFactory> factoriesToBeAdded) {
this.excluder = excluder;
this.fieldNamingStrategy = fieldNamingStrategy;
this.instanceCreators = instanceCreators;
this.constructorConstructor = new ConstructorConstructor(instanceCreators);
this.serializeNulls = serializeNulls;
this.complexMapKeySerialization = complexMapKeySerialization;
this.generateNonExecutableJson = generateNonExecutableGson;
this.htmlSafe = htmlSafe;
this.prettyPrinting = prettyPrinting;
this.lenient = lenient;
this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
this.longSerializationPolicy = longSerializationPolicy;
this.datePattern = datePattern;
this.dateStyle = dateStyle;
this.timeStyle = timeStyle;
this.builderFactories = builderFactories;
this.builderHierarchyFactories = builderHierarchyFactories;
List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);
// the excluder must precede all adapters that handle user-defined types
factories.add(excluder);
// users' type adapters
factories.addAll(factoriesToBeAdded);
// type adapters for basic platform types
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);
// type adapters for composite and user-defined types
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);
}
主要是做了一些數據的初始化以及適配器的添加工作,現在來看toJson()方法
public String toJson(Object src) {
if (src == null) {
//返回一個null 字串
return toJson(JsonNull.INSTANCE);
}
return toJson(src, src.getClass());
}
public String toJson(Object src, Type typeOfSrc) {
//創建字符串編輯器,繼承自writer,內部就是StringBuffer 和一個寫入鎖,後邊的字段會寫入他裏邊然後toString 出來。
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);
} catch (AssertionError e) {
AssertionError error = new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage());
error.initCause(e);
throw error;
} finally {
writer.setLenient(oldLenient);
writer.setHtmlSafe(oldHtmlSafe);
writer.setSerializeNulls(oldSerializeNulls);
}
}
其實主要有兩個地方。
1.TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc));
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
//TypeToken<T> 類字面翻譯是類型令牌,其實就是保存了這個類的屬性,類型和hashcode等值爲後期操作準備
//typeTokenCache 內部是一個線程安全的ConcurrentHashMap ,它主要用來緩存類型令牌,如果能夠獲取到值,那說明之前已經有了相同的類型令牌,也就是說是同一個,如果有了就直接返回
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;
}
// the key and value type parameters always agree
//鍵和值類型參數始終一致 這個目前沒搞明白要幹啥,唯一覺得可行的就是併發訪問時可能出現這種onfoingCal不爲空,有待近一步理解
FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
if (ongoingCall != null) {
return ongoingCall;
}
try {
FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
threadCalls.put(type, call);
//factories 是適配器集合,通過遍歷找到相關類型
for (TypeAdapterFactory factory : factories) {
//根據上邊我們的實體類 type可以判斷最終執行 ReflectiveTypeAdapterFactory 的create方法返回值不爲空,所以他的適配器類型是這樣確定的 ,如果不算自定義是41種適配器
TypeAdapter<T> candidate = factory.create(this, type);
if (candidate != null) {
call.setDelegate(candidate);
typeTokenCache.put(type, candidate);
return candidate;
}
}
throw new IllegalArgumentException("GSON (" + GsonBuildConfig.VERSION + ") cannot handle " + type);
} finally {
threadCalls.remove(type);
if (requiresThreadLocalCleanup) {
calls.remove();
}
}
}
進入ReflectiveTypeAdapterFactory看下 create幹了什麼事
@Override public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
Class<? super T> raw = type.getRawType();
if (!Object.class.isAssignableFrom(raw)) {
return null; // it's a primitive!
}
//這是一個構造實例函數的構造器,序列化過程沒有用到
ObjectConstructor<T> constructor = constructorConstructor.get(type);
return new Adapter<T>(constructor, getBoundFields(gson, type, raw));
}
接着看 getBoundFields 函數,所有的反射操作都是在它裏邊完成的
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {
//有序的hashMap 用於存儲反射獲取的接口聲明的字段
Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
if (raw.isInterface()) {
return result;
}
Type declaredType = type.getType();
while (raw != Object.class) {
//反射獲取所有字段field集合
Field[] fields = raw.getDeclaredFields();
for (Field field : fields) {
//提取註解數值
boolean serialize = excludeField(field, true);
boolean deserialize = excludeField(field, false);
if (!serialize && !deserialize) {
continue;
}
//類中的成員變量爲private,故必須進行此操作 設置權限 調用的是 setAccessible
accessor.makeAccessible(field);
//獲取當前field字段函數類型
Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
//變量名稱 例如 name. 集合中只有一個值
List<String> fieldNames = getFieldNames(field);
BoundField previous = null;
for (int i = 0, size = fieldNames.size(); i < size; ++i) {
String name = fieldNames.get(i);
if (i != 0) serialize = false; // only serialize the default name
//對變量名稱,變量類型,及序列化和非序列華 判斷的封裝,
BoundField boundField = createBoundField(context, field, name,
TypeToken.get(fieldType), serialize, deserialize);
//然後以函數名爲鍵將BoundField 存起來
BoundField replaced = result.put(name, boundField);
if (previous == null) previous = replaced;
}
if (previous != null) {
throw new IllegalArgumentException(declaredType
+ " declares multiple JSON fields named " + previous.name);
}
}
type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
raw = type.getRawType();
}
return result;
}
getBoundFields返回的數據結構 現在我們回到create 方法 看 return new Adapter<T>(constructor, getBoundFields(gson, type, raw)); 的返回值Adaper<T>類,他繼承TypeAdapter 同時保存了 構造器和變量的BoundField 數據集合即變量名稱的相關信息,並且重寫了讀和寫 構造函數,
這些操作完成後我們會拿到一個 TypeAdapter<?> 對象,準備工作已經做完了,下面進入真題,開始序列化,過程
TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc)); 拿到adapter
2.((TypeAdapter<Object>) adapter).write(writer, src)
((TypeAdapter<Object>) adapter).write(writer, src); 調用的是Adapte<T> 類的write 開始寫,我們進入Adapter<T>類看下write方法實現 ,Adapter<T> 是 ReflectiveTypeAdapterFactory 類的內部靜態類。
@Override public void write(JsonWriter out, T value) throws IOException {
//這裏 如果 value 也就是我們需要序列化的 爲null 將會寫入一個空 null
if (value == null) {
out.nullValue();
return;
}
//正式開始序列化的流操作 起始的 “{”
out.beginObject();
try {
for (BoundField boundField : boundFields.values()) {
if (boundField.writeField(value)) {
//保存 函數名
out.name(boundField.name);
//開始拼接寫入鍵和值
boundField.write(out, value);
}
}
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
// 結束序列化流操作 結束 “}”
out.endObject();
}
現在看下boundField 的write 的實現。
ReflectiveTypeAdapterFactory 類 createBoundField 方法內 122 行 不同版本可能有差異。
前邊我們說過BoundField 類是組裝了變量名 及序列化 和反序列化判斷 的封裝類,同時還有幾個抽象方法,現在我們要看的就是BoundFileld 的實現的地方。
static abstract class BoundField {
final String name;
final boolean serialized;
final boolean deserialized;
protected BoundField(String name, boolean serialized, boolean deserialized) {
this.name = name;
this.serialized = serialized;
this.deserialized = deserialized;
}
abstract boolean writeField(Object value) throws IOException, IllegalAccessException;
abstract void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException;
abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException;
}
具體實現:
return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) {
@SuppressWarnings({"unchecked", "rawtypes"}) // the type adapter and field type always agree
@Override void write(JsonWriter writer, Object value)
throws IOException, IllegalAccessException {
//通過調用write ,通過反射, Field的get 方法獲取field 對應函數值 即變量值。
Object fieldValue = field.get(value);
// 實體類 類型 變量 類型 的封裝 同時繼承自TypeAdapter 重寫了方法
TypeAdapter t = jsonAdapterPresent ? typeAdapter
: new TypeAdapterRuntimeTypeWrapper(context, typeAdapter, fieldType.getType());
//開始寫
t.write(writer, fieldValue);
}
@Override void read(JsonReader reader, Object value)
throws IOException, IllegalAccessException {
Object fieldValue = typeAdapter.read(reader);
if (fieldValue != null || !isPrimitive) {
field.set(value, fieldValue);
}
}
@Override public boolean writeField(Object value) throws IOException, IllegalAccessException {
if (!serialized) return false;
Object fieldValue = field.get(value);
return fieldValue != value; // avoid recursion for example for Throwable.cause
}
};
現在進入到
TypeAdapterRuntimeTypeWrapper<T> 類的 write 方法中
@Override
public void write(JsonWriter out, T value) throws IOException {
// Order of preference for choosing type adapters
// First preference: a type adapter registered for the runtime type
// Second preference: a type adapter registered for the declared type
// Third preference: reflective type adapter for the runtime type (if it is a sub class of the declared type)
// Fourth preference: reflective type adapter for the declared type
// 實體類 的Type
TypeAdapter chosen = delegate;
/變量值類型的Type
Type runtimeType = getRuntimeTypeIfMoreSpecific(type, value);
// 這裏如果變量值不是基本的數據類型 比對成功就會重新負值(這裏的理解不是特別到位,有待進一步理解)
if (runtimeType != type) {
TypeAdapter runtimeTypeAdapter = context.getAdapter(TypeToken.get(runtimeType));
if (!(runtimeTypeAdapter instanceof ReflectiveTypeAdapterFactory.Adapter)) {
// The user registered a type adapter for the runtime type, so we will use that
chosen = runtimeTypeAdapter;
} else if (!(delegate instanceof ReflectiveTypeAdapterFactory.Adapter)) {
// The user registered a type adapter for Base class, so we prefer it over the
// reflective type adapter for the runtime type
chosen = delegate;
} else {
// Use the type adapter for runtime type
chosen = runtimeTypeAdapter;
}
}
chosen.write(out, value);
}
假設我們解析到了name 函數 調用到 string 類型適配器的write
public static final TypeAdapter<String> STRING = new TypeAdapter<String>() {
@Override
public String read(JsonReader in) throws IOException {
JsonToken peek = in.peek();
if (peek == JsonToken.NULL) {
in.nextNull();
return null;
}
/* coerce booleans to strings for backwards compatibility */
if (peek == JsonToken.BOOLEAN) {
return Boolean.toString(in.nextBoolean());
}
return in.nextString();
}
@Override
public void write(JsonWriter out, String value) throws IOException {
// 進入jsonWriter 開始流寫入
out.value(value);
}
};
進入 jsonWriter 的value 方法 繞了這麼大一圈終於到點了。
public JsonWriter value(String value) throws IOException {
if (value == null) {
return nullValue();
}
// 這個方法是拼接 key 的方法,也就是變量名稱,同時他還判斷了是否在他之前添加“,” 分割符的操作
// 例如 ,“name”
writeDeferredName();
//開始寫入value 即變量值之前的操作,確定在key 後面添加“:” 分割符
// 此時拼接 例如 ,“name": 前通過反射獲取數組時我們用到了一個有序hashMap ,那麼此時name已經是第二個操作的變量了 ,那麼寫入的字串爲 {"age":30,"name":
beforeValue();
//開始寫入name 的值
string(value);
//寫入完成,重新回到 Adapter<T> 方法的write for 循環中,我們的demo 有三個字段,會走三遍
return this;
}
for (BoundField boundField : boundFields.values()) {//走三遍
if (boundField.writeField(value)) {
//保存 函數名
out.name(boundField.name);
//開始拼接寫入鍵和值
boundField.write(out, value);
}
}
上邊說的比較粗糙,那有人就會問了,他是如何保存狀態的,因爲我們列出的只是一個簡單的對像序列化,沒有嵌套 數組等,所以我們沒有想到這些 ,其他主要有以下幾個方法
//獲取保存的標示狀態 ,用於確定下一步操作
peek();
// 新起一行
newline();
//存儲標示
replaceTop(int topOfStack)
最終還是回到開始的地方
public String toJson(Object src, Type typeOfSrc) {
StringWriter writer = new StringWriter();
toJson(src, typeOfSrc, writer);
return writer.toString();
}
通過流將json 字符串返回回來,到此gson 的toJson 過程就結束了。
重新理下詳細過程
1.獲取一個流對象
2.通過遍歷找到實例對象的適配器類型
3.通過反射獲取到那個變量名和變量類型的集合
4.遍歷集合獲取每個變量的值並且找到適配器類型
5.開始通過流寫入拼接數據 { "key" : value ,. . . }
閱讀過程中如果有理解不到位還請各位讀者多加提醒。