Android-Gson源碼實(shí)現(xiàn)

1.fromJson

public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
    Object object = fromJson(json, (Type) classOfT);
    return Primitives.wrap(classOfT).cast(object);
}

這個(gè)方法的實(shí)現(xiàn)亭敢,是調(diào)用了傳入Type的fromJson

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;
}

這里調(diào)用的fromJson是傳入了一個(gè)Reader對(duì)象

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;
}

這里調(diào)用的fromJson是傳入了JsonReader對(duì)象斟湃,所有的fromJson都會(huì)調(diào)用下面這個(gè)

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;
        // 將傳入的Type實(shí)例封裝成一個(gè)TypeToken實(shí)例
        TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
        // 根據(jù)對(duì)應(yīng)的TypeToken苇侵,從typeTokenCache這個(gè)Map緩存中取出對(duì)應(yīng)的TypeAdapter
        TypeAdapter<T> typeAdapter = getAdapter(typeToken);
        // 調(diào)用對(duì)應(yīng)的TypeAdapter的實(shí)現(xiàn)類的read方法故河,將對(duì)應(yīng)的JsonReader封裝Json字符串之后的對(duì)象解析轉(zhuǎn)換成對(duì)應(yīng)的實(shí)體類
        T object = typeAdapter.read(reader);
        return object;
    } catch (EOFException e) {
        /*
        * For compatibility with JSON 1.5 and earlier, we return null for empty
        * documents instead of throwing.
        */
        if (isEmpty) {
            return null;
        }
        throw new JsonSyntaxException(e);
    } catch (IllegalStateException e) {
        throw new JsonSyntaxException(e);
    } catch (IOException e) {
        // TODO(inder): Figure out whether it is indeed right to rethrow this as       JsonSyntaxException
        throw new JsonSyntaxException(e);
    } finally {
        reader.setLenient(oldLenient);
    }
}

在這里,是通過TypeAdapter對(duì)象獲取到了返回的Object對(duì)象爽待,而TypeAdapter是通過getAdapter方法得到的:

  @SuppressWarnings("unchecked")
  public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
    // 1.首先嘗試從Gson中的Map緩存中取出對(duì)應(yīng)的TypeAdapter實(shí)現(xiàn)類對(duì)象
    TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
    if (cached != null) {
      return (TypeAdapter<T>) cached;
    }

    // 2.
    // calls是一個(gè)Gson內(nèi)部的ThreadLocal對(duì)象咧最,是一個(gè)ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>>類型的,
    // 其內(nèi)部存的是一個(gè)Map集合逐纬,而FutureTypeAdapter是TypeAdapter的代理類對(duì)象
    // 使用ThreadLocal來緩存FutureTypeAdapter對(duì)象蛔屹,是本地防止getAdapter()的重入調(diào)用
    // 其實(shí)就是避免無限遞歸導(dǎo)致一直創(chuàng)建TypeAdapter,最終因?yàn)闊o限遞歸導(dǎo)致棧溢出的問題
    Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
    boolean requiresThreadLocalCleanup = false;
    if (threadCalls == null) {
      threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
      calls.set(threadCalls);
      requiresThreadLocalCleanup = true;
    }

    // 3.如果在ThreadLocal中的Map中找到了TypeToken對(duì)應(yīng)的FutureTypeAdapter豁生,則直接返回
    // FutureTypeAdapter是一個(gè)委托類兔毒,其實(shí)就是代理類,內(nèi)部保存TypeToken對(duì)應(yīng)的TypeAdapter實(shí)例
    // FutureTypeAdapter也是繼承自TypeAdapter
    FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
    if (ongoingCall != null) {
      return ongoingCall;
    }

    try {
      //創(chuàng)建FutureTypeAdapter沛硅,保存在ThreadLocal對(duì)象中
      FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
      threadCalls.put(type, call);

      for (TypeAdapterFactory factory : factories) {
        // 在這里可能會(huì)發(fā)生無限遞歸的情況眼刃,即在new Adapter<T>(constructor, getBoundFields(gson, type, raw));
        // getBoundFields方法中,會(huì)調(diào)用createBoundField方法封裝每個(gè)Field摇肌,這個(gè)時(shí)候就會(huì)獲取每個(gè)Field的TypeAdapter
        // 這里遞歸的主要原因就是create內(nèi)部創(chuàng)建Adapter的時(shí)候,會(huì)調(diào)用getBoundFields方法仪际,其內(nèi)部又會(huì)調(diào)用createBoundField方法围小,
        // 在createBoundField方法中又會(huì)調(diào)用Gson.getAdapter昵骤,這樣又遞歸到了Gson.getAdapter,而使用了一個(gè)ThreadLocal肯适,
        // 因?yàn)橐呀?jīng)提前put了变秦,遞歸調(diào)用的時(shí)候,第二次同樣的類型執(zhí)行到上面就會(huì)通過return ongoingCall;返回框舔,而不會(huì)執(zhí)行到這里繼續(xù)遞歸
        // 使用ThreadLocal的目的就是在遞歸調(diào)用getAdapter的時(shí)候蹦玫,出現(xiàn)TypeToken相同的情況下,在第一次遞歸時(shí)就提前返回刘绣,然后在使用外部類型的TypeAdapter
        TypeAdapter<T> candidate = factory.create(this, type);
        if (candidate != null) {
          // 將通過TypeAdapterFactory.create創(chuàng)建的TypeAdapter委托給對(duì)應(yīng)的FutureTypeAdapter對(duì)象
          call.setDelegate(candidate);
          // 緩存對(duì)應(yīng)的TypeAdapter
          typeTokenCache.put(type, candidate);
          return candidate;
        }
      }
      throw new IllegalArgumentException("GSON cannot handle " + type);
    } finally {
      threadCalls.remove(type);

      if (requiresThreadLocalCleanup) {
        calls.remove();
      }
    }
  }

上面getAdapter代碼中會(huì)遍歷存儲(chǔ)TypeAdapterFactory的factories樱溉,尋找對(duì)應(yīng)的TypeAdapterFactory實(shí)例,比如返回一個(gè)Bean類的對(duì)象的話纬凤,則會(huì)調(diào)用ReflectiveTypeAdapterFactory福贞,通過這個(gè)Factory.create創(chuàng)建對(duì)應(yīng)的TypeAdapter實(shí)例。

2.屬性說明

  private final ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>> calls
      = new ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>>();

calls是一個(gè)ThreadLocal停士,這個(gè)ThreadLocal緩存了一個(gè)Map集合挖帘,通過對(duì)應(yīng)的TypeToken在當(dāng)前線程中取出對(duì)應(yīng)的FutureTypeAdapter,然后返回恋技。增加一個(gè)ThreadLocal緩存的目的就是為了避免遞歸查找導(dǎo)致無限創(chuàng)建TypeAdapter實(shí)例而出現(xiàn)棧溢出拇舀。
比如:

public class Article {
    public Article article;
    .....
    .....
    .....
    
    
}

在這個(gè)例子中,一個(gè)Article蜻底,其內(nèi)部有一個(gè)屬性骄崩,也是Article類型的,如果不使用ThreadLocal朱躺,那么就會(huì)出現(xiàn)無限遞歸創(chuàng)建對(duì)應(yīng)的TypeAdapter實(shí)例進(jìn)行解析刁赖。而使用委托類,則會(huì)通過委托類對(duì)象长搀,其內(nèi)部調(diào)用已經(jīng)創(chuàng)建的TypeAdapter進(jìn)行read宇弛。這樣就會(huì)復(fù)用同一個(gè)TypeAdapter實(shí)例。
可以參考下面的文章中的內(nèi)容:

http://www.reibang.com/p/aef252db9869

3.ReflectiveTypeAdapterFactory.BoundField相關(guān)

在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);
    // 調(diào)用ReflectiveTypeAdapterFactory.getBoundFields方法返回一個(gè)Map集合源请,
    // 這個(gè)Map集合的key其實(shí)就是Field的name枪芒,而BoundField其實(shí)就是根據(jù)對(duì)應(yīng)的字段類型、字段名稱等進(jìn)行封裝委托
    return new Adapter<T>(constructor, getBoundFields(gson, type, raw));
  }
  private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {
    Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
    if (raw.isInterface()) {
      return result;
    }

    Type declaredType = type.getType();
    // 如果真實(shí)類型是Object類型谁尸,則結(jié)束循環(huán)
    while (raw != Object.class) {
      // 獲取該類型的所有內(nèi)部屬性舅踪,getDeclaredFields()方法是獲取本類型,不包括父類的所有屬性(包括私有屬性)
      Field[] fields = raw.getDeclaredFields();
      // 遍歷所有字段
      for (Field field : fields) {
        boolean serialize = excludeField(field, true);
        boolean deserialize = excludeField(field, false);
        if (!serialize && !deserialize) {
          continue;
        }
        field.setAccessible(true);
        // 獲取字段的類型
        Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
        // 獲取字段名稱良蛮,因?yàn)橥ㄟ^Gson注解可以給一個(gè)字段設(shè)置多個(gè)name
        List<String> fieldNames = getFieldNames(field);
        BoundField previous = null;
        for (int i = 0, size = fieldNames.size(); i < size; ++i) {
          String name = fieldNames.get(i);
          // 只對(duì)默認(rèn)名稱進(jìn)行序列化數(shù)據(jù)
          if (i != 0) serialize = false; // only serialize the default name
          // 創(chuàng)建BoundField
          BoundField boundField = createBoundField(context, field, name,
              TypeToken.get(fieldType), serialize, deserialize);
          // 替換Map中已有的value
          BoundField replaced = result.put(name, boundField);
          if (previous == null) previous = replaced;
        }
        if (previous != null) {
          // 如果previous不為null抽碌,說明Map中在根據(jù)name創(chuàng)建BoundField的時(shí)候,已經(jīng)有一個(gè)BoundField
          // 這樣的情況說明一個(gè)name有了兩個(gè)BoundField决瞳,則說明一個(gè)類中出現(xiàn)兩個(gè)字段名相同的字段
          throw new IllegalArgumentException(declaredType
              + " declares multiple JSON fields named " + previous.name);
        }
      }
      type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
      // 獲取父類型货徙,繼續(xù)循環(huán)左权,直到父類型為Object為止。
      // 這樣做的目的就是為了Bean類有繼承的情況痴颊,能對(duì)父類屬性進(jìn)行解析赏迟。
      raw = type.getRawType();
    }
    return result;
  }

在通過ReflectiveTypeAdapterFactory.create創(chuàng)建TypeAdapter實(shí)例的時(shí)候,通過getBoundFields創(chuàng)建一個(gè)Map集合,主要就是為了對(duì)類的所有屬性進(jìn)行封裝。

  // 根據(jù)Field創(chuàng)建BoundField时甚,并且封裝Field的讀寫操作
  private ReflectiveTypeAdapterFactory.BoundField createBoundField(
      final Gson context, final Field field, final String name,
      final TypeToken<?> fieldType, boolean serialize, boolean deserialize) {
    // 判斷是否是基本數(shù)據(jù)類型
    final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType());
    // special casing primitives here saves ~5% on Android...
    JsonAdapter annotation = field.getAnnotation(JsonAdapter.class);
    TypeAdapter<?> mapped = null;
    if (annotation != null) {
      mapped = jsonAdapterFactory.getTypeAdapter(
          constructorConstructor, context, fieldType, annotation);
    }
    final boolean jsonAdapterPresent = mapped != null;
    // Gson嘗試獲取該Field字段類型的TypeAdapter
    // 這里的context其實(shí)就是Gson實(shí)例,這里其實(shí)又是調(diào)用了Gson.getAdapter
    if (mapped == null) mapped = context.getAdapter(fieldType);

    // 使用final糕再,是便于內(nèi)部類使用
    final TypeAdapter<?> typeAdapter = mapped;
    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 {
        Object fieldValue = field.get(value);
        TypeAdapter t = jsonAdapterPresent ? typeAdapter
            : new TypeAdapterRuntimeTypeWrapper(context, typeAdapter, fieldType.getType());
        t.write(writer, fieldValue);
      }
      // 執(zhí)行Json數(shù)據(jù)的讀取解析操作,然后轉(zhuǎn)換成Object對(duì)象饰豺,通過Field.set亿鲜,給對(duì)應(yīng)的字段設(shè)置value值。
      @Override void read(JsonReader reader, Object value)
          throws IOException, IllegalAccessException {
        // 通過該屬性的類型對(duì)應(yīng)的TypeAdapter嘗試讀取json串
        //如果是基礎(chǔ)類型冤吨,則直接讀取蒿柳,
        //如果是復(fù)合類型則遞歸之前的流程
        // 因?yàn)樵贕son.fromJson方法中,最終就是通過調(diào)用typeAdapter.read進(jìn)行json串解析
        // 而這里是又被typeAdapter.read調(diào)用漩蟆,而這里又調(diào)用了typeAdapter.read(reader);
        // 其實(shí)就是一個(gè)遞歸調(diào)用流程垒探,即在typeAdapter.read內(nèi)部調(diào)用了typeAdapter.read(reader);
        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
      }
    };
  }

4.ReflectiveTypeAdapterFactory.read

找到對(duì)應(yīng)的TypeAdapter之后,就會(huì)調(diào)用對(duì)應(yīng)的read方法怠李。以反射方式實(shí)現(xiàn)為例子:

主要是借助了ReflectiveTypeAdapterFactory圾叼,每個(gè)TypeAdapter其實(shí)都是通過對(duì)應(yīng)的Factory的create方法獲取到的。而ReflectiveTypeAdapterFactory中有一個(gè)內(nèi)部類捺癞,就是繼承了TypeAdapter類

public static final class Adapter<T> extends TypeAdapter<T> {
    // 用于反射獲取對(duì)象
    private final ObjectConstructor<T> constructor;

    private final Map<String, BoundField> boundFields;

    Adapter(ObjectConstructor<T> constructor, Map<String, BoundField> boundFields) {
        this.constructor = constructor;
        this.boundFields = boundFields;
    }

    @Override public T read(JsonReader in) throws IOException {

        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }

        T instance = constructor.construct();

        try {

            in.beginObject();

            while (in.hasNext()) {
                String name = in.nextName();
                BoundField field = boundFields.get(name);
                // 判斷boundFields中對(duì)應(yīng)的字段名稱是否為空夷蚊,如果為空則跳過
                // 這就是為什么json串中有更多字段的數(shù)據(jù),可以使用更少屬性的類來解析髓介,因?yàn)檫@里會(huì)跳過
                if (field == null || !field.deserialized) {
                    in.skipValue();
                } else {
                    // 調(diào)用BoundField.read方法惕鼓,其內(nèi)部會(huì)調(diào)用TypeAdapter.read
                    field.read(in, instance);
                }
            }
        } catch (IllegalStateException e) {
            throw new JsonSyntaxException(e);
        } catch (IllegalAccessException e) {
            throw new AssertionError(e);
        }

        in.endObject();
        return instance;
    }

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

        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();
    }

}

Gson解析中,使用ReflectiveTypeAdapterFactory的解析過程:


image.png

5.使用TypeToken需要為什么要使用匿名內(nèi)部類的方式唐础?

new TypeToken<BaseResponse>(){}.getType()箱歧,如果這里不采用創(chuàng)建匿名內(nèi)部類的方式去獲取Type,而是new TypeToken<BaseResponse>().getType()一膨,那么這樣創(chuàng)建的一個(gè)對(duì)象呀邢,在經(jīng)過編譯為.class的時(shí)候,其泛型類型就會(huì)因?yàn)轭愋筒脸兂闪薕bject豹绪,這樣就沒辦法獲取到準(zhǔn)確的Type价淌。
而在這里使用{},其實(shí)就是創(chuàng)建匿名內(nèi)部類對(duì)象,在創(chuàng)建匿名內(nèi)部類對(duì)象输钩,那么其實(shí)就可以認(rèn)為是創(chuàng)建了一個(gè)新的類豺型,就是將舊的TypeToken類的中的泛型T都替換成了BaseResponse的新類仲智。這個(gè)新類买乃,其實(shí)就可以認(rèn)為是TypeToken中的泛型T都為BaseResponse的一個(gè)新類,而不是使用T了钓辆。這樣剪验,在編譯成.class文件的時(shí)候,就不會(huì)因?yàn)榉盒筒脸霈F(xiàn)T變成Object前联,而是編譯成.class之后功戚,其實(shí)就是T都是BaseResponse類型。
匿名內(nèi)部類對(duì)象似嗤,其實(shí)可以認(rèn)為是創(chuàng)建了一個(gè)新的匿名內(nèi)部類啸臀,然后使用這個(gè)匿名內(nèi)部類來創(chuàng)建了一個(gè)對(duì)象。

6.Excluder排序器

主要是為了處理一些不需要序列化和不需要反序列化的一些字段的烁落。

(2)返回list集合的fromJson

public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {

    // type的值是java.util.list<類路徑>

    TypeAdapter<?> cached = typeTokenCache.get(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
    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();
        }
    }
}

而返回List集合乘粒,是通過CollectionTypeAdapterFactory這個(gè)類里面的內(nèi)部類來實(shí)現(xiàn)的:

private static final class Adapter<E> extends TypeAdapter<Collection<E>> {

    private final TypeAdapter<E> elementTypeAdapter;

    private final ObjectConstructor<? extends Collection<E>> constructor;

    public Adapter(Gson context, Type elementType,

    TypeAdapter<E> elementTypeAdapter,

    ObjectConstructor<? extends Collection<E>> constructor) {
        this.elementTypeAdapter = new TypeAdapterRuntimeTypeWrapper<E>(context, elementTypeAdapter, elementType);
        this.constructor = constructor;
    }

    @Override public Collection<E> read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }

        Collection<E> collection = constructor.construct();
        in.beginArray();
        while (in.hasNext()) {
            E instance = elementTypeAdapter.read(in);
            collection.add(instance);
        }

        in.endArray();  
        return collection;
    }

    @Override public void write(JsonWriter out, Collection<E> collection) throws IOException {

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

        out.beginArray();
        for (E element : collection) {
            elementTypeAdapter.write(out, element);
        }  
        out.endArray();
    }
}

在內(nèi)部類的Adapter中都會(huì)有一個(gè)read方法,而read方法中伤塌,會(huì)在內(nèi)部調(diào)用elementTypeAdapter這個(gè)類的read方法灯萍,而這個(gè)類的read方法,其實(shí)是調(diào)用的TypeAdapterRuntimeTypeWrapper的read方法每聪,而TypeAdapterRuntimeTypeWrapper的read方法是調(diào)用了ReflectiveTypeAdapterFactory的內(nèi)部類Adapter的read方法旦棉,也就是通過反射拿到一個(gè)個(gè)的對(duì)象。說明List的形式其實(shí)就是通過反射拿到一個(gè)Connection對(duì)象药薯,再通過反射拿到一個(gè)個(gè)的對(duì)象绑洛,然后將這些對(duì)象放到Connection中。Map的方式其實(shí)是類似的童本。

(3)返回Map集合

返回Map集合中真屯,Gson.java類中的getAdapter方法中的TypeAdapter<T> candidate = factory.create(this, type);最終是調(diào)用的MapTypeAdapterFactory類的create方法。而在這里巾陕,會(huì)分別創(chuàng)建兩個(gè)TypeAdapter讨跟,也就是KeyAdapter和ValueAdapter,這兩個(gè)Adapter都是ObjectTypeAdapter的實(shí)例對(duì)象鄙煤。

如果key是一個(gè)String晾匠、int、boolean這樣的類型的梯刚,則KeyTypeAdapter對(duì)象其實(shí)就是從TypeAdapters中的對(duì)應(yīng)的TypeAdapter的實(shí)現(xiàn)類凉馆。而value如果是Object,那么則是通過ReflectiveTypeAdapterFactory的靜態(tài)final內(nèi)部類Adapter返回對(duì)應(yīng)的Object的,其實(shí)就是通過反射的方式返回的澜共。

JsonReader解析:

(1)beginObject()

int peeked = PEEKED_NONE;

public void beginObject() throws IOException {

    int p = peeked;

    if (p == PEEKED_NONE) {

        p = doPeek();

    }

    if (p == PEEKED_BEGIN_OBJECT) {

        push(JsonScope.EMPTY_OBJECT);

        peeked = PEEKED_NONE;

    } else {

        throw new IllegalStateException("Expected BEGIN_OBJECT but was " + peek() +   locationString());

    }

}

peeked是個(gè)很重要的變量向叉,默認(rèn)值為PEEKED_NONE。在上面的方法中嗦董,調(diào)用了一個(gè)方法doPeek()母谎,這個(gè)類可以說是JsonReader類的核心方法之一。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末京革,一起剝皮案震驚了整個(gè)濱河市奇唤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌匹摇,老刑警劉巖咬扇,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異廊勃,居然都是意外死亡懈贺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門坡垫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來梭灿,“玉大人,你說我怎么就攤上這事葛虐√ピ矗” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵屿脐,是天一觀的道長(zhǎng)涕蚤。 經(jīng)常有香客問我,道長(zhǎng)的诵,這世上最難降的妖魔是什么万栅? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮西疤,結(jié)果婚禮上烦粒,老公的妹妹穿的比我還像新娘。我一直安慰自己代赁,他們只是感情好扰她,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著芭碍,像睡著了一般徒役。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上窖壕,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天忧勿,我揣著相機(jī)與錄音杉女,去河邊找鬼。 笑死鸳吸,一個(gè)胖子當(dāng)著我的面吹牛熏挎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晌砾,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼坎拐,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了贡羔?” 一聲冷哼從身側(cè)響起廉白,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乖寒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體院溺,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡楣嘁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了珍逸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逐虚。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖谆膳,靈堂內(nèi)的尸體忽然破棺而出叭爱,到底是詐尸還是另有隱情,我是刑警寧澤漱病,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布买雾,位于F島的核電站,受9級(jí)特大地震影響杨帽,放射性物質(zhì)發(fā)生泄漏漓穿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一注盈、第九天 我趴在偏房一處隱蔽的房頂上張望晃危。 院中可真熱鬧,春花似錦老客、人聲如沸僚饭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鳍鸵。三九已至,卻和暖如春朴则,著一層夾襖步出監(jiān)牢的瞬間权纤,已是汗流浹背钓简。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留汹想,地道東北人外邓。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像古掏,于是被迫代替她去往敵國(guó)和親损话。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 引言 使用Gson已經(jīng)有好長(zhǎng)時(shí)間了槽唾,但是一直停留在使用的層面上丧枪,因此在對(duì)它的好奇心尚未消失之前,我得跟它做個(gè)了斷 ...
    horseLai閱讀 788評(píng)論 0 1
  • 基于非墨上一篇關(guān)于泛型的文章,不知道大家是否已經(jīng)做好了閱讀Gson源碼的準(zhǔn)備庞萍?本篇文章,非墨將簡(jiǎn)單帶大家過一下Gs...
    非墨Zero閱讀 4,773評(píng)論 6 14
  • 簡(jiǎn)介 Gson是google提供的一款Json解析框架拧烦,基本很多項(xiàng)目都會(huì)使用到。Gson自帶的容錯(cuò)機(jī)制能夠使解析過...
    拔蘿卜占坑閱讀 9,296評(píng)論 2 6
  • 1.import static是Java 5增加的功能,就是將Import類中的靜態(tài)方法钝计,可以作為本類的靜態(tài)方法來...
    XLsn0w閱讀 1,228評(píng)論 0 2
  • 文\霉霉 今天是2017年7月2日恋博,耳機(jī)里來回循環(huán)的是只有影子的《遇瑩》 不知道是為什么,每當(dāng)人失意時(shí)私恬,總喜歡把悲...
    總會(huì)遇到愛你的人閱讀 375評(píng)論 0 1