追蹤解析Gson源碼(1)

零 前期準備

0 FBI WARNING

文章異常囉嗦且繞彎。html

1 版本

Gson 版本 : gson 2.8.5java

IDE : idea 2018.3sql

2 Gson 簡介

Gson 是谷歌開源的 java json 解析工具。市場上同類的開源產品還有 Fastjson、Jackson、json-lib等。json

其實幾款產品的差異都很細微,Gson 有谷歌的信仰加成,因此在這裏進行一次源碼分析。api

3 Bean Demo

package ioc;

/**
 * java bean
 */
public class Person {

    private String name;
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

4 main方法

import com.google.gson.Gson;

public class JsonTest {

    public static void main(String[] args){
        //示例 json 字符串
        String json =
                "{" +
                "   \"name\": \"zhangsan\"," +
                "   \"age\": 11" +
                "}";

        //初始化解析器
        Gson gson = new Gson();

        //json to bean
        Person person = gson.fromJson(json,Person.class);
        System.out.println(person.getName());
        System.out.println(person.getAge());

        //bean to json
        String json2 = gson.toJson(person);
        System.out.println(json2);
    }
}

一 初始化 Gson 解析器

1 Gson 構造方法

該 part 的起點:ide

Gson gson = new Gson();

追蹤 Gson 的無參構造器:工具

//Gson.class
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.class
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, String datePattern, int dateStyle,
    int timeStyle, List<TypeAdapterFactory> builderFactories,
    List<TypeAdapterFactory> builderHierarchyFactories,
    List<TypeAdapterFactory> factoriesToBeAdded) {
    
    //排除器,在序列化對象的時候會根據使用者設置的規則排除一些數據
    //排除策略須要使用者自行實現 ExclusionStrategy 接口來制定
    this.excluder = excluder;

    //fieldNamingStrategy 負責命名規則的肯定(好比 大駝峯命名、小駝峯命名、下劃線命名 等)
    //選擇不一樣的 fieldNamingStrategy 會在輸出 json 字符串的時候把字段名稱轉成不一樣的命名形式
    //此處的值能夠直接選擇 FieldNamingPolicy 枚舉類中的已經存儲的策略,也能夠自行實現 FieldNamingStrategy 接口
    //此處默認爲 FieldNamingPolicy.IDENTITY,即不改變
    this.fieldNamingStrategy = fieldNamingStrategy;

    //instanceCreators 是一個用來存儲實現了 InstanceCreator 接口的對象的 map
    //每個 InstanceCreator 的實現類用來反射獲取一種特定類型的 bean 對象
    //InstanceCreator 在 Gson 中沒有實現類,使用者能夠自行定製
    //此處爲空 map
    this.instanceCreators = instanceCreators;

    //ConstructorConstructor 用來統一調度 instanceCreators
    this.constructorConstructor = new ConstructorConstructor(instanceCreators);

    //serializeNulls 是一個 boolean 類型的對象,用以表示是否支持空對象的序列化
    //此處傳入的是 DEFAULT_SERIALIZE_NULLS,值爲 false,是一個定義在 Gson 中的常量
    this.serializeNulls = serializeNulls;

    //將 Map 序列化的過程當中,會存在一個問題,即 Map 的 key 值是一個複雜對象(java bean 等)
    //若是 complexMapKeySerialization 設置爲 false,則直接調用對象的 toString() 方法獲取字符串
    //設置爲 true 的狀況下會去嘗試解析此對象,通常狀況下要配合特定的 TypeAdapter 使用
    //默認爲 false
    this.complexMapKeySerialization = complexMapKeySerialization;

    //是否要生成不可執行的 json
    //默認爲 false
    this.generateNonExecutableJson = generateNonExecutableGson;

    //是否對 html 進行編碼,即對部分符號進行轉義(=、<、> 等)
    //默認爲 true
    this.htmlSafe = htmlSafe;

    //在輸出的時候格式化 json
    //默認爲 false
    this.prettyPrinting = prettyPrinting;

    //設置 json 的自定義標準
    //默認 false ,即爲 json 標準的數據格式
    this.lenient = lenient;

    //用於支持 float 類型的特殊值,好比 Infinity(無窮大) 或 -Infinity(負無窮大) 等
    //默認爲 false
    this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;

    //設置對 long 類型的變量,是解析成字符串仍是解析爲 long 類型
    //默認爲解析成 long 類型
    this.longSerializationPolicy = longSerializationPolicy;

    //如下三行用於設置日期格式和時間格式
    //datePattern 是日期和時間的字符串格式表達,在此處爲 null
    //dateStyle 與 timeStyle 爲日期和時間格式的編碼
    //以 int 常量形式存放在 java.text.DateFormat 中
    //此處均爲默認值
    //須要注意的是默認狀況下 Gson 的日期解析不太符合國人的習慣
    this.datePattern = datePattern;
    this.dateStyle = dateStyle;
    this.timeStyle = timeStyle;

    //此處爲空
    this.builderFactories = builderFactories;

    //此處爲空
    this.builderHierarchyFactories = builderHierarchyFactories;

    //TypeAdapter 是一個接口,用於序列化和反序列化某種特定的類型
    //TypeAdapterFactory 是 TypeAdapter 的包裝類
    List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();

    //TypeAdapters 是 TypeAdapter 和 TypeAdapterFactory 的通用工具類
    //處理 JsonElement 類型對象的 TypeAdapterFactory
    //JsonElement 是 Gson 工具包中的一個類
    factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);

    //處理 Object 類型對象的 TypeAdapterFactory
    factories.add(ObjectTypeAdapter.FACTORY);

    //excluder 是一個省略了類型的 TypeAdapterFactory
    //根據官方註釋,excluder 須要先於全部使用者自定義的 TypeAdapterFactory 去執行
    factories.add(excluder);

    //使用者自定義的 TypeAdapterFactory
    factories.addAll(factoriesToBeAdded);

    //處理 String 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.STRING_FACTORY);

    //處理 Integer / int 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.INTEGER_FACTORY);

    //處理 Boolean / boolean 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.BOOLEAN_FACTORY);

    //處理 Byte / byte 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.BYTE_FACTORY);

    //處理 Short / short 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.SHORT_FACTORY);

    //處理 Long / long 類型對象的 TypeAdapterFactory
    TypeAdapter<Number> longAdapter = longAdapter(longSerializationPolicy);
    factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter));

    //處理 Double / double 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.newFactory(double.class, Double.class,
            doubleAdapter(serializeSpecialFloatingPointValues)));

    //處理 Float / float 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.newFactory(float.class, Float.class,
            floatAdapter(serializeSpecialFloatingPointValues)));

    //處理 Number 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.NUMBER_FACTORY);

    //處理 AtomicInteger 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY);

    //處理 AtomicBoolean 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY);

    //處理 AtomicBoolean 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter)));

    //處理 AtomicLongArray 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter)));

    //處理 AtomicIntegerArray 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY);

    //處理 Character / char 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.CHARACTER_FACTORY);

    //處理 StringBuilder 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.STRING_BUILDER_FACTORY);

    //處理 StringBuffer 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.STRING_BUFFER_FACTORY);

    //處理 BigDecimal 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));

    //處理 BigInteger 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));

    //處理 URL 類型對象的 TypeAdapterFactory
    //java.net.URL
    factories.add(TypeAdapters.URL_FACTORY);

    //處理 URI 類型對象的 TypeAdapterFactory
    //java.net.URI
    factories.add(TypeAdapters.URI_FACTORY);

    //處理 UUID 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.UUID_FACTORY);

    //處理 Currency 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.CURRENCY_FACTORY);

    //處理 Locale 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.LOCALE_FACTORY);

    //處理 InetAddress 類型對象的 TypeAdapterFactory
    //java.net.InetAddress
    factories.add(TypeAdapters.INET_ADDRESS_FACTORY);

    //處理 BitSet 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.BIT_SET_FACTORY);

    //處理 Date 類型對象的 TypeAdapterFactory
    //java.util.Date
    factories.add(DateTypeAdapter.FACTORY);

    //處理 Calendar 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.CALENDAR_FACTORY);

    //處理 Time 類型對象的 TypeAdapterFactory
    factories.add(TimeTypeAdapter.FACTORY);

    //處理 Date 類型對象的 TypeAdapterFactory
    //java.sql.Date
    factories.add(SqlDateTypeAdapter.FACTORY);

    //處理 Timestamp 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.TIMESTAMP_FACTORY);

    //處理 Array 類型對象的 TypeAdapterFactory
    factories.add(ArrayTypeAdapter.FACTORY);

    //處理 Class 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.CLASS_FACTORY);

    //處理 Collection 類型對象的 TypeAdapterFactory
    factories.add(new CollectionTypeAdapterFactory(constructorConstructor));

    //處理 Map 類型對象的 TypeAdapterFactory
    //會受到 complexMapKeySerialization 的影響
    factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));

    //處理 JsonAdapter 類型對象的 TypeAdapterFactory
    //JsonAdapter 是一個 Gson 中的註解
    this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
    factories.add(jsonAdapterFactory);

    //處理 Enum 類型對象的 TypeAdapterFactory
    factories.add(TypeAdapters.ENUM_FACTORY);

    //反射分解對象的 TypeAdapterFactory
    factories.add(new ReflectiveTypeAdapterFactory(
        constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));

    this.factories = Collections.unmodifiableList(factories);
}

從這裏能夠看出,Gson 的初始化時期提供了很是豐富的設置選項。ui

2 GsonBuilder

設置 Gson 的這些選項須要經過 GsonBuilder :this

Gson gson = new GsonBuilder()

    //如下方法均爲設置 excluder
    //設置版本號
    .setVersion(1)
    //設置忽略某種修飾詞修飾的變量
    //此處忽略 protected 修飾的變量
    .excludeFieldsWithModifiers(Modifier.PROTECTED)
    //設置使用 Expose 註解,用於忽略某個字段
    //默認狀況下是不使用 Expose 註解的
    .excludeFieldsWithoutExposeAnnotation()
    //設置不序列化內部類
    .disableInnerClassSerialization()
    //批量添加序列化時使用的排除策略
    //此方法爲不定參方法
    .setExclusionStrategies(exclusionStrategy)
    //添加一個序列化時使用的排除策略
    .addSerializationExclusionStrategy(exclusionStrategy)
    //添加一個反序列化時使用的排除策略
    .addDeserializationExclusionStrategy(exclusionStrategy)

    //本質上如下三個方法均爲設置 TypeAdapter
    .registerTypeAdapter(String.class, TypeAdapters.STRING)
    .registerTypeAdapterFactory(TypeAdapters.STRING_FACTORY)
    .registerTypeHierarchyAdapter(String.class, TypeAdapters.STRING)

    //設置 dateStyle、datePattern、timeStyle
    .setDateFormat("yyyy-MM-dd HH:mm:ss")
    .setDateFormat(DateFormat.DATE_FIELD)
    .setDateFormat(DateFormat.DATE_FIELD,DateFormat.AM_PM_FIELD)

    //如下兩個方法本質上是同樣的,均爲設置 fieldNamingPolicy 屬性
    .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY)
    .setFieldNamingStrategy(FieldNamingPolicy.IDENTITY)

    //設置 complexMapKeySerialization = true
    .enableComplexMapKeySerialization()

    //設置 longSerializationPolicy = LongSerializationPolicy.STRING
    //即 long 類型的數據在序列化的時候會轉成 String
    .setLongSerializationPolicy(LongSerializationPolicy.STRING)

    //設置 serializeNulls = true
    .serializeNulls()

    //設置 prettyPrinting = true
    .setPrettyPrinting()

    //設置 generateNonExecutableJson = true
    .generateNonExecutableJson()

    //設置 lenient = true
    .setLenient()

    //設置 escapeHtmlChars = false
    .disableHtmlEscaping()

    //設置 serializeSpecialFloatingPointValues = true
    .serializeSpecialFloatingPointValues()

    //建立解析器對象
    .create();

3 Excluder

在上述設置中,有一大塊是關於排除器 excluder 的設置。excluder 的實現邏輯依賴 ExclusionStrategy 的自定義實現類,追蹤一下 ExclusionStrategy 接口:

//實現 
public interface ExclusionStrategy {

    //設置忽略的變量,須要傳入 FieldAttributes
    //FieldAttributes 是在 Gson 中定義的 Field 的包裝類
    public boolean shouldSkipField(FieldAttributes f);

    //設置要忽略的 class
    public boolean shouldSkipClass(Class<?> clazz);
}

fieldNamingPolicy 則須要 FieldNamingStrategy 的自定義實現類,追蹤一下 FieldNamingStrategy 接口:

public interface FieldNamingStrategy {

  //在這個方法中實現自定義的命名規則
  public String translateName(Field f);
}

FieldNamingPolicy 是一個實現了 FieldNamingStrategy 接口的枚舉類,其中實現了多套 translateName(...) 方法可供選擇。

二 TypeAdapter 和 TypeAdapterFactory

在 Gson 中封裝了不一樣類型的讀寫的業務組裝類是各個 TypeAdapter(適配器),這裏先來關注一下其具體實現。

1 父類與接口

先來看一下 TypeAdapterFactory 接口:

public interface TypeAdapterFactory {

  //只有一個方法,用於根據解析器和變量類型來建立 TypeAdapter
  <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type);
}

再來看一下 TypeAdapter 抽象類:

public abstract class TypeAdapter<T> {

    //寫入方法,主要的指揮 JsonWriter 進行業務處理
    public abstract void write(JsonWriter out, T value) throws IOException;

    //讀取方法,主要是指揮 JsonReader 進行業務操做
    public abstract T read(JsonReader in) throws IOException;

    //該抽象類中還提供了其它的方法,在此例中沒有用到,暫時忽略
}

2 StringTypeAdapter

關注一下下列這行代碼:

factories.add(TypeAdapters.STRING_FACTORY);

factories 是一個列表,來追蹤一下 TypeAdapters.STRING_FACTORY :

//TypeAdapters.class
public static final TypeAdapterFactory STRING_FACTORY = newFactory(String.class, STRING);

先來看一下定義在 TypeAdapters 中的 STRING 變量:

//TypeAdapters.class
public static final TypeAdapter<String> STRING = new TypeAdapter<String>() {

    //此方法用於反序列化時讀取值
    @Override
    public String read(JsonReader in) throws IOException {

        //in.peek() 方法會獲取到最新的 JsonReader 操做指令,並轉換成下一個要操做的字符類型
        //在後面的 part 裏還會提到
        JsonToken peek = in.peek();

        //讀取到 null
        if (peek == JsonToken.NULL) { 
            in.nextNull();
            return null;
        }

        //讀取到 boolean 類型的值
        if (peek == JsonToken.BOOLEAN) { 
            return Boolean.toString(in.nextBoolean());
        }

        //除了 null 和 boolean 以外,都視做 String 進行返回
        return in.nextString(); 
    }

    //此方法用於序列化時寫入值
    @Override
    public void write(JsonWriter out, String value) throws IOException {
        out.value(value);
    }
};

繼續追蹤 newFactory(...) 方法:

//TypeAdapters.class
public static <TT> TypeAdapterFactory newFactory(final Class<TT> type, final TypeAdapter<TT> typeAdapter) {

    return new TypeAdapterFactory() {

      @SuppressWarnings("unchecked") 
      @Override
      public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
          //typeToken.getRawType() 會獲取到這個 TypeToken 所須要的
        return typeToken.getRawType() == type ? (TypeAdapter<T>) typeAdapter : null;
      }

      //常規的從新 toString() 方法
      @Override
      public String toString() {
        return "Factory[type=" + type.getName() + ",adapter=" + typeAdapter + "]";
      }
    };
}

從這裏能夠看出,TypeAdapterFactory 本質上只是 TypeAdapter 的包裝類,只是作一個類型的斷定工做,若是斷定爲相同,就會返回傳入的 TypeAdapter。

通常的類型的 TypeAdpter 的操做邏輯都比較相似,不贅述了。

2 ReflectiveTypeAdapter

對於通常的自定義類,好比使用者自定義的 java bean 等,並不是 jdk 自帶的基本數據類型,就都須要 ReflectiveTypeAdapter 來進行解析。

先來看一下 ReflectiveTypeAdapterFactory 的 create() 方法:

//ReflectiveTypeAdapterFactory.class
public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
    Class<? super T> raw = type.getRawType();

    //要確保 type 中獲取出來的 class 的類型是 Object 的子類
    //若是不是的話就表明這是基本類型,基本類型的解析不該該使用該適配器
    //因此返回 null
    if (!Object.class.isAssignableFrom(raw)) {
      return null;
    }
    
    //constructor 用於反射建立對象
    ObjectConstructor<T> constructor = constructorConstructor.get(type);

    //Adapter 是 ReflectiveTypeAdapterFactory 的靜態內部類,繼承了 TypeAdapter
    return new Adapter<T>(constructor, getBoundFields(gson, type, raw));
}

來繼續追蹤一下 Adapter 的主要方法:

public static final class Adapter<T> extends TypeAdapter<T> {

    //此處 read(...) 和 write(...) 的代碼比較相似
    //主要步驟是經過反射建立出對象,並抓取其全部的變量,逐個存入

    public T read(JsonReader in) throws IOException {

        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        //調用構造器反射建立出對象
        T instance = constructor.construct();
        //如下代碼是 Gson 讀出字符串中的部分,並用反射填入到對象中的過程
        try {
            in.beginObject();
            while (in.hasNext()) {
                String name = in.nextName();
                //BoundField 是 Gson 對 jdk 中的 Field 類的加強
                BoundField field = boundFields.get(name);
                if (field == null || !field.deserialized) {
                    in.skipValue();
                } else {
                    field.read(in, instance);
                }
            }
        } catch (IllegalStateException e) {
            throw new JsonSyntaxException(e);
        } catch (IllegalAccessException e) {
            throw new AssertionError(e);
        }
        in.endObject();
        return instance;
    }

    public void write(JsonWriter out, T value) throws IOException {

        if (value == null) {
            out.nullValue();
            return;
        }

        out.beginObject();
        //如下是 Gson 從對象中獲取到數據並寫成字符串的過程
        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();
    }
}

具體的步驟實際上是對 java 反射的深度定製化應用,不展開了。

以上過程在 JsonReader 和 JsonWriter 的應用中會有相似展開。至於 JsonReader 和 JsonWriter 會在後續進行追蹤。

To Be Continued ...

相關文章
相關標籤/搜索