Gson源码解析

1,523 阅读5分钟

简介

java对象和JSON之间相互转换的库。

虽然现在PB协议已经成为主流,还是来看下Gson库实现的思路。

使用

  1. 引入
dependencies {
  implementation 'com.google.code.gson:gson:2.9.0'
}
  1. 转换
class BagOfPrimitives {
  private int value1 = 1;
  private String value2 = "abc";
  private transient int value3 = 3;
  BagOfPrimitives() {
    // no-args constructor
  }
}

// Serialization
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);  
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);

源码分析

构造方法

Gson gson = new Gson();

public Gson() {
  this(Excluder.DEFAULT, DEFAULT_FIELD_NAMING_STRATEGY,
      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,
      DEFAULT_USE_JDK_UNSAFE,
      LongSerializationPolicy.DEFAULT, DEFAULT_DATE_PATTERN, DateFormat.DEFAULT, DateFormat.DEFAULT,
      Collections.<TypeAdapterFactory>emptyList(), Collections.<TypeAdapterFactory>emptyList(),
      Collections.<TypeAdapterFactory>emptyList(), DEFAULT_OBJECT_TO_NUMBER_STRATEGY, DEFAULT_NUMBER_TO_NUMBER_STRATEGY);
}

Gson(Excluder excluder, FieldNamingStrategy fieldNamingStrategy,
    Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
    boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
    boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
    boolean useJdkUnsafe,
    LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
    int timeStyle, List<TypeAdapterFactory> builderFactories,
    List<TypeAdapterFactory> builderHierarchyFactories,
    List<TypeAdapterFactory> factoriesToBeAdded,
    ToNumberStrategy objectToNumberStrategy, ToNumberStrategy numberToNumberStrategy) {
   
   ··········
  
  List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();

  // built-in type adapters that cannot be overridden
  factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
  factories.add(ObjectTypeAdapter.getFactory(objectToNumberStrategy));

  // the excluder must precede all adapters that handle user-defined types
  factories.add(excluder);

  (1)重点关注这里
  // 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(NumberTypeAdapter.getFactory(numberToNumberStrategy));
  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));
  // Add adapter for LazilyParsedNumber because user can obtain it from Gson and then try to serialize it again
  factories.add(TypeAdapters.newFactory(LazilyParsedNumber.class, TypeAdapters.LAZILY_PARSED_NUMBER));
  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);

  if (SqlTypesSupport.SUPPORTS_SQL_TYPES) {
    factories.add(SqlTypesSupport.TIME_FACTORY);
    factories.add(SqlTypesSupport.DATE_FACTORY);
    factories.add(SqlTypesSupport.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);
  (2)关注这里。
  factories.add(new ReflectiveTypeAdapterFactory(
      constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));

  this.factories = Collections.unmodifiableList(factories);
}
  1. factories里面添加了大量的基本数据类型的TypeAdapter

  2. factories最后添加了一个反射的TypeAdapter

找一个基本数据类型看下。

factories.add(TypeAdapters.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) {
      (1)判断TypeToken里面的type类型
      return typeToken.getRawType() == type ? (TypeAdapter<T>) typeAdapter : null;
    }
    @Override public String toString() {
      return "Factory[type=" + type.getName() + ",adapter=" + 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);
  }
};
  1. 判断TypeToken里面的type类型,如果是String,返回String的TypeAdapter`。

  2. TypeAdapterread方法会返回json里面的string实体value

反序列化

BagOfPrimitives bagOfPrimitives = gson.fromJson(json, BagOfPrimitives.class);

特别注意:

上面那个方法不适合对象本身是泛型的。

如果指定对象的任何字段都是泛型的,这个方法可以正常工作,只是对象本身不应该是泛型的。对于对象是泛型的情况,调用fromJson(String, Type)。

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;
  }
  (1)构造一个 StringReader。
  StringReader reader = new StringReader(json);
  T target = (T) fromJson(reader, typeOfT);
  return target;
}

public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
  (2)构造一个 JsonReader
  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;
    (3)根据Class对象创建一个TypeToken
    TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
    (4)根据TypeToken创建一个TypeAdapter。
    TypeAdapter<T> typeAdapter = getAdapter(typeToken);
    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);
  } catch (AssertionError e) {
    AssertionError error = new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage());
    error.initCause(e);
    throw error;
  } finally {
    reader.setLenient(oldLenient);
  }
}

注释3的TypeToken对象。

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

看下注释4怎么获取TypeAdapter

public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
  (1)尝试从缓存中拿去TypeAdapter。  
  TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
  if (cached != null) {
    return (TypeAdapter<T>) cached;
  }
    
  (2)从ThreadLocal中获取  
  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 agree3)创建静态代理类。为啥创建代理类?
  FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
  if (ongoingCall != null) {
    return ongoingCall;
  }

  try {
    FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
    threadCalls.put(type, call);

    (4)遍历Gson构造方法中的TypeAdapter工厂。
    for (TypeAdapterFactory factory : factories) {
      (5)看下create方法。 
      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 {
  (6)移除FutureTypeAdapter
    threadCalls.remove(type);
    (7)移除当前线程的ThreadLocal里面内容。
    if (requiresThreadLocalCleanup) {
      calls.remove();
    }
  }
}

特别注意:

  1. 为什么缓存存储一份,还要用ThreadLocal再次缓存?

先看下注释5的代码

ReflectiveTypeAdapterFactory

@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!
  }
  (1)获取当前Class的构造函数。  
  ObjectConstructor<T> constructor = constructorConstructor.get(type);
  (2)重点看下这里 getBoundFields 
  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();
  while (raw != Object.class) {
    Field[] fields = raw.getDeclaredFields();
    for (Field field : fields) {
      boolean serialize = excludeField(field, true);
      boolean deserialize = excludeField(field, false);
      if (!serialize && !deserialize) {
        continue;
      }
      ReflectionHelper.makeAccessible(field);
      Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
      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
        (3)看下这里。
        BoundField boundField = createBoundField(context, field, name,
            TypeToken.get(fieldType), serialize, deserialize);
        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;
}

private ReflectiveTypeAdapterFactory.BoundField createBoundField(
    final Gson context, final Field field, final String name,
    final TypeToken<?> fieldType, boolean serialize, boolean deserialize) {
  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;
  (4)又会递归调用getAdapter
  if (mapped == null) mapped = context.getAdapter(fieldType);

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

为什么缓存存储一份,还要用ThreadLocal再次缓存?

这里就清楚了。是为了解决递归调用的。

image.png

static class BagOfPrimitives {
    private int value1 = 1;
    private String value2 = "abc";
    private transient int value3 = 3;
    private Book book = new Book();

    /**
     * 特别注意这里
     */
    public BagOfPrimitives bagOfPrimitives;

    BagOfPrimitives() {
        // no-args constructor
    }
}
  1. 如果是常规数据类型,就使用构造方法创建的TypeAdapter
  2. 不是常规数据类型,就反射创建,并通过反射获取类里面的属性,依次调用getAdapter创建。

总结:

核心原理:

image.png

小结:

  1. Gson 构造方法里面创建了许多常规数据类型的TypeAdapter
  2. 最后添加了一个反射的TypeAdapter
  3. 如果是常规数据类型,就使用构造方法创建的TypeAdapter
  4. 不是常规数据类型,就反射创建,并通过反射获取类里面的属性,依次调用getAdapter创建。

特别注意:

如何解决递归调用?

  1. 通过Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls保存当前TypeToken。里面有相同类型。就直接返回。

  2. 可以查看getAdapter方法。

参考: