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

阅读过程中如果有理解不到位还请各位读者多加提醒。

 

 

 

 

 

 

 

 

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