Android—Gson原理解析

JsonElement

  • 抽象类
  • 代表json串的某一个元素
  • 某一个元素:
    • JsonObject
    • JsonArray
    • JsonPrimitive(基本类型)
    • JsonNull

JsonElement的四个子类

  • JsonObject、JsonArray、JsonPrimitive、JsonNull

JsonPrimitive 

该类对Java的基本类型及其对应的对象类进行了封装(短整长,单精双精,字符<表示为单字符字符串>,布尔)

Gson对象的产生

通过new Gson()方式

通过这种方式创建的Gson对象,将用Java的反射机制来完成json的解析,将大量默认的TypeAdapterFactory添加到factories中,生成默认的Gson对象

通过GsonBuilder的方式

TypeAdapter:该类的作用就是把json串封装成你指定的Java对象

通过GsonBuilder注册TypeAdapter,并把TypeAdapter封装成TypeAdpterFactory对象

将封装成的TypeAdapterFactory通过GsonBuilder的create传入Gson对象中并返回

调用gson.fromJson方法,调用getTypeAdapter方法返回你自定义的Adapter

下面解析new Gson()方式的序列化过程

String json = "{ \"name\":\"java书籍\", \"authors\":[\"Jerry\",\"Tom\"]}";
Book book = new Gson().fromJson(json, Book.class);
String s = new Gson().toJson(book);

public class Book implements Serializable {
    private String name;
    private ArrayList<String> authors;

    public Book(String name, ArrayList<String> authors) {
        this.name = name;
        this.authors = authors;
    }
}

反序列化过程

public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
    boolean isEmpty = true;
   // 接受不符合规定的json变量的值
    boolean oldLenient = reader.isLenient();
    //强制设置为接受
    reader.setLenient(true);
    try {
//此处相当于调用了一次 JsonReader 中的 doPeek() 方法,返回下一个令牌的类型而不消耗它,设置当前令牌
      reader.peek();
      isEmpty = false;
        //TypeToken 本质上是 Class 的增强封装类
      TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
      //根据要转化的实体类型,获取相应的适配器
      TypeAdapter<T> typeAdapter = getAdapter(typeToken);
      //通过适配器生成实体类
      T object = typeAdapter.read(reader);
      return object;
    } catch (EOFException e) {

     .......

    }

  }

可以看到最终结果是adapter的read方法返回了我们需要的对象。
先看 getAdapter (typeToken) 方法:

public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
    // 先判断缓存
    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
    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 是构建gson对象时候添加的类型适配器工厂值 
     
      for (TypeAdapterFactory factory : factories) {
 
       //循环寻找可以处理该类型的factory ,factory.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);
}

        TypeAdapter<T> candidate = factory.create(this, type);根据type获取相应的typeAdapter , 然后返回,new Gson()的话,在构造函数会给添加许多的adpter,
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) {
    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);
    //添加factory
 
    // 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);
  }

因为我们采用的是new Gson(),由于我们没有添加自定义的Adapter,最后只能由ReflectiveTypeAdapterFactory进行处理。

直接看ReflectiveTypeAdapterFactory的create方法

@Override public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
    Class<? super T> raw = type.getRawType();
    //这里用于比对类型,如果不是相应的类型就返回null
    //确定此* {@code Class}对象表示的类或接口是否与指定的{{code code}}参数所表示的类或接口相同,或者是该类或接口的超类或父接口。 。如果是,则返回{@code true}; *否则返回{@code false}
    //很显然,这里返回的是true 应为我们的类是TestMode 是一个class类
    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(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;
      }
      accessor.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
        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;
}

debug截图:

 可以看到getBoundFields()方法结果返回的result是应该map对象,里面存着key为我们类属性名,value为adapterFactory的对象。

了解了getAapter方法,我们接下来分析ReflectiveTypeAdapterFactory的read方法。

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

 

这里的field就是刚刚getBoundFields()中获取到的,放在map中的一个。

可以看到它调用的是field.read(in, instance);

return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) {
    void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException {
        Object fieldValue = field.get(value);
        TypeAdapter t = jsonAdapterPresent ? mapped : new TypeAdapterRuntimeTypeWrapper(context, mapped, fieldType.getType());
        ((TypeAdapter)t).write(writer, fieldValue);
    }

    void read(JsonReader reader, Object value) throws IOException, IllegalAccessException {
        Object fieldValue = mapped.read(reader);
        if (fieldValue != null || !isPrimitive) {
            field.set(value, fieldValue);
        }

    }

   根据debug截图可以看出,fieldValue是typeAdapter调用read之后解析出来的值,就跟我们现在所跟的流程一样,因为这里“java书籍“是String所以会到String对应的Adapter中解析,如果是我们自定义类的话还是会走再一遍反射。可以看到value是Book对象,

 都还是null,field对应的是name属性,所以接下来set方法将fieldValue设置到Book对象的name属性中。

 可以看到set方法后,book对象的name就有值了。

看下read方法最后返回的就是解析完成的对象,

序列化toJson同样需要经过反射,

可以看ReflectiveTypeAdapterFactory的write方法,

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

 它也是调boundField的方法,boundField.write(out, value);

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

 可以看到write之后,out属性被写上了“name“:”java书籍“。

 最终结果返回的是writer.toString()。

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值