美文网首页Android
Gson源码分析(一)

Gson源码分析(一)

作者: nothingren | 来源:发表于2017-05-30 18:22 被阅读430次

    Json解析一直是网络通信中重要的数据解析框架。而Gson和FastJson是最为常用的两个Json解析框架。这一章节主要介绍Gson的原理。Gson的一个典型使用例子如下:

            String jsonString = "{\"name\":\"renyiguang\"}";
            Gson gson = new Gson();
            TestModel testModel = gson.fromJson(jsonString, TestModel.class);
    

    Gson的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);//1获取TypeToken
          TypeAdapter<T> typeAdapter = getAdapter(typeToken);//2获取TypeAdapter
          T object = typeAdapter.read(reader);//3解析
          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);
        }
      }
    

    如上,fromJson()方法主要分三个步骤:1获取TypeToken,2获取TypeAdapter,3利用TypeAdapter解析。
    下面就按照这三个步骤分析。
    (1)TypeToken
    TypeToken的get()方法源码如下:

      public static TypeToken<?> get(Type type) {
        return new TypeToken<Object>(type);
      }
    
      TypeToken(Type type) {
        this.type = $Gson$Types.canonicalize($Gson$Preconditions.checkNotNull(type));
        this.rawType = (Class<? super T>) $Gson$Types.getRawType(this.type);
        this.hashCode = this.type.hashCode();
      }
    

    TypeToken保存了待解析数据的Type类型。
    (2)TypeAdapter
    TypeAdapter是通过getAdapter()方法获取。getAdapter()方法源码如下:

      public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
        TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);//缓存获取TypeAdapter
        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) {//从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();
          }
        }
      }
    

    当typeTokenCache中没有TypeToken对应的TypeAdapter时,就从factories中查找对应的TypeAdapter。factories查找TypeAdapter的标准是TypeAdapterFactory的create()方法返回非空。
    factories的初始化在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>();
    
        // 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);
    
        // user's type adapters
        factories.addAll(typeAdapterFactories);//添加自定义的TypeAdapterFactory
    
        // 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);
      }
    

    如上factories里面包含了Gson能解析的所有的数据格式。下面以STRING_FACTORY为例来说明。

      public static final TypeAdapterFactory STRING_FACTORY = newFactory(String.class, STRING);
    
      public static <TT> TypeAdapterFactory newFactory(
          final Class<TT> type, final TypeAdapter<TT> typeAdapter) {
        return new TypeAdapterFactory() {
          @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
          @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
            return typeToken.getRawType() == type ? (TypeAdapter<T>) typeAdapter : null;
          }
          @Override public String toString() {
            return "Factory[type=" + type.getName() + ",adapter=" + typeAdapter + "]";
          }
        };
      }
    

    newFactory()方法返回的TypeAdapterFactory的create()方法就做了一件事,验证type的一致性。即如果需要处理的数据类型为String,则返回TypeAdapter,否则返回null。String类型对应的TypeAdapter源码如下:

      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 {
          out.value(value);
        }
      };
    

    关于Gson解析,简单的流程已经介绍完毕。下面就从解析的角度注重分析。

    相关文章

      网友评论

        本文标题:Gson源码分析(一)

        本文链接:https://www.haomeiwen.com/subject/tscvxxtx.html