Gson源碼解析之-toJson

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 ,. . .   }

閱讀過程中如果有理解不到位還請各位讀者多加提醒。

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章