Gson原理分析

官网地址:https://github.com/google/gson
官方描述:A Java serialization/deserialization library to convert Java Objects into JSON and back

JsonElement

该类是一个抽象类,代表着json串的某一个元素。这个元素可以是一个Json对象(JsonObject)、可以是一个数组(JsonArray)、可以是一个Java的基本类型(JsonPrimitive)、当然也可以为null(JsonNull);JsonObject,JsonArray,JsonPrimitive,JsonNull都是JsonElement这个抽象类的子类。JsonElement提供了一系列的方法来判断当前的JsonElement是否是上述子类的一种:比如isJsonObject()用来判断当前的json元素是否是一个Json对象,它的实现很简单且这里巧妙地应用了Java的多态机制:

  /**
   * provides check for verifying if this element is a Json object or not.
   *
   * @return true if this element is of type {@link JsonObject}, false otherwise.
   */
  public boolean isJsonObject() {
    
    
    return this instanceof JsonObject;
  }

同样的既然有isJsonObject()等这样的判断,该类也提供了把当前JsonElement作为上述子类的一种返回的方法:

  public JsonObject getAsJsonObject() {
    
    
    if (isJsonObject()) {
    
    
      return (JsonObject) this;
    }
    throw new IllegalStateException("Not a JSON Object: " + this);
  }

各个JsonElement的关系可以用如下图表示:
在这里插入图片描述
JsonObject对象可以看成 name/values的集合,而这些values就是一个个JsonElement,他们的结构可以用如下图表示:
在这里插入图片描述

JsonPrimitive:

JsonElement的子类,该类对Java的基本类型及其对应的包装类进行了封装,并通过setValue方法为value赋值。

/**
 * A class representing a Json primitive value. A primitive value
 * is either a String, a Java primitive, or a Java primitive
 * wrapper type.
 *
 * @author Inderjeet Singh
 * @author Joel Leitch
 */
public final class JsonPrimitive extends JsonElement {
    
    

  private static final Class<?>[] PRIMITIVE_TYPES = {
    
     int.class, long.class, short.class,
      float.class, double.class, byte.class, boolean.class, char.class, Integer.class, Long.class,
      Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class };

  private Object value;

	...

}

需要注意的是对于Character类型的json元素需要特殊处理:

  void setValue(Object primitive) {
    
    
    if (primitive instanceof Character) {
    
    
      // convert characters to strings since in JSON, characters are represented as a single
      // character string
      char c = ((Character) primitive).charValue();
      this.value = String.valueOf(c);
    } else {
    
    
      $Gson$Preconditions.checkArgument(primitive instanceof Number
              || isPrimitiveOrString(primitive));
      this.value = primitive;
    }
  }

同时对于传入的其他json类型通过checkArgument进行过滤,如果不是Number或者String和 PRIMITIVE_TYPES里的一种的话,就会抛出异常。

  private static boolean isPrimitiveOrString(Object target) {
    
    
    if (target instanceof String) {
    
    
      return true;
    }

    Class<?> classOfPrimitive = target.getClass();
    for (Class<?> standardPrimitive : PRIMITIVE_TYPES) {
    
    
      if (standardPrimitive.isAssignableFrom(classOfPrimitive)) {
    
    
        return true;
      }
    }
    return false;
  }

同样类似JsonElement,该类也提供了判断某一个json元素是否是某一类型的判断和把某一json元素作为某一类型返回的方法:

  /**
   * Check whether this primitive contains a Number.
   *
   * @return true if this primitive contains a Number, false otherwise.
   */
  public boolean isNumber() {
    
    
    return value instanceof Number;
  }

  /**
   * convenience method to get this element as a Number.
   *
   * @return get this element as a Number.
   * @throws NumberFormatException if the value contained is not a valid Number.
   */
  @Override
  public Number getAsNumber() {
    
    
    return value instanceof String ? new LazilyParsedNumber((String) value) : (Number) value;
  }

对于Java的几个基本类型用JsonPrimitive类进行了封装, 还遗漏了一个null的json元素,Gson也对它进行了单独的处理,就是JsonNull。

JsonNull:

该类没什么可说的,为不可变类。当然在json中所有的JsonNullObject 调用equals方法判断的话都是相等的。

JsonArray:

Json的数组包含的其实也是一个个Json串。所以不难猜出JsonArray中用一个集合类,源码中用List<JsonElement>来添加json数组中的每个元素。(详见源码,很简单)

public final class JsonArray extends JsonElement implements Iterable<JsonElement> {
    
    
  private final List<JsonElement> elements;

  /**
   * Creates an empty JsonArray.
   */
  public JsonArray() {
    
    
    elements = new ArrayList<JsonElement>();
  }

  ...

}
  

JsonObject:

json对象类,包含了键值对,键是字符串类型,值是一个JsonElement。
用 LinkedTreeMap<String, JsonElement> members来保存。

TypeAdapter的工作原理

该类将一个java对象转为json,将一个json转为java对象。
定义一个类型(比如一个java类)对应的json样式。

先看下JsonParser类,该类是final类型,它的作用就将json串解析成JsonElement对象,提供了三个重载方法:parse(String json),parse(Reader json),parse(JsonReader json),分别可以解析String串、Reader输入流、JsonReader输入流。parse(String json),parse(Reader json)最终都会调用parse(JsonReader json)方法。

JsonReader主要作用就是读取json字符串并转化为一个token流,而JsonParser就是根据这个token流进行json语法分析并转为java对象。

测试代码:

public class JsonParserTest {
    
    

    public static void main(String[] args) {
    
    
        String json = "{ \"name\":\"java书籍\", \"authors\":[\"Jerry\",\"Tom\"]}";
        JsonParser parser = new JsonParser();
        JsonElement jsonElement = parser.parse(json);
        System.out.println("jsonElement=" + jsonElement);
        System.out.println(jsonElement.getAsJsonObject().get("authors").isJsonArray());
    }

}

追踪parse方法,最终调用了Streams.parse(JsonReader)方法

  /**
   * Takes a reader in any state and returns the next value as a JsonElement.
   */
  public static JsonElement parse(JsonReader reader) throws JsonParseException {
    
    
    boolean isEmpty = true;
    try {
    
    
      reader.peek();
      isEmpty = false;
      return TypeAdapters.JSON_ELEMENT.read(reader);
    } catch (EOFException e) {
    
    
      /*
       * For compatibility with JSON 1.5 and earlier, we return a JsonNull for
       * empty documents instead of throwing.
       */
      if (isEmpty) {
    
    
        return JsonNull.INSTANCE;
      }
      // The stream ended prematurely so it is likely a syntax error.
      throw new JsonSyntaxException(e);
    } catch (MalformedJsonException e) {
    
    
      throw new JsonSyntaxException(e);
    } catch (IOException e) {
    
    
      throw new JsonIOException(e);
    } catch (NumberFormatException e) {
    
    
      throw new JsonSyntaxException(e);
    }
  }

该方法最终执行ypeAdapters.JSON_ELEMENT.read(reader)并返回组装好的JsonElement对象,具体看看该方法:

    /**
     * JSON_ELEMENT是一个匿名内部类对象,实现了TypeAdapter抽象类
     */
    public static final TypeAdapter<JsonElement> JSON_ELEMENT = new TypeAdapter<JsonElement>() {
    
    

        //该方法就是读取一个json,将它转化为java对象,并返回该java对象
        @Override
        public JsonElement read(JsonReader in) throws IOException {
    
    
            //调用peek()方法对json串进行读取和解析,并返回对应的JsonToken类型
            switch (in.peek()) {
    
    
                case STRING://如果是字符串类型,封装为JsonPrimitive并返回之
                    return new JsonPrimitive(in.nextString());
                case NUMBER:
                    String number = in.nextString();
                    return new JsonPrimitive(new LazilyParsedNumber(number));
                case BOOLEAN:
                    return new JsonPrimitive(in.nextBoolean());
                case NULL:
                    in.nextNull();
                    return JsonNull.INSTANCE;
                case BEGIN_ARRAY:
                    //如果是数组类型,则递归调用read方法解析成JsonElement对象,添加到array中
                    JsonArray array = new JsonArray();
                    in.beginArray();
                    while (in.hasNext()) {
    
    
                        array.add(read(in));
                    }
                    in.endArray();
                    return array;//返回JsonArray
                case BEGIN_OBJECT:
                    //如果是Json对象类型,解析该json对象,获取name和value放入object中,value可能是JsonElement,所以要递归调用read(in)
                    JsonObject object = new JsonObject();
                    in.beginObject();
                    while (in.hasNext()) {
    
    
                        object.add(in.nextName(), read(in));
                    }
                    in.endObject();
                    return object;//返回JsonObject
                case END_DOCUMENT:
                case NAME:
                case END_OBJECT:
                case END_ARRAY:
                default:
                    throw new IllegalArgumentException();
            }
        }

        //将一个java对象转化为一个json
        @Override
        public void write(JsonWriter out, JsonElement value) throws IOException {
    
    
            if (value == null || value.isJsonNull()) {
    
    
                out.nullValue();
            } else if (value.isJsonPrimitive()) {
    
    
                JsonPrimitive primitive = value.getAsJsonPrimitive();
                if (primitive.isNumber()) {
    
    
                    out.value(primitive.getAsNumber());
                } else if (primitive.isBoolean()) {
    
    
                    out.value(primitive.getAsBoolean());
                } else {
    
    
                    out.value(primitive.getAsString());
                }

            } else if (value.isJsonArray()) {
    
    
                out.beginArray();
                for (JsonElement e : value.getAsJsonArray()) {
    
    
                    write(out, e);
                }
                out.endArray();

            } else if (value.isJsonObject()) {
    
    
                out.beginObject();
                for (Map.Entry<String, JsonElement> e : value.getAsJsonObject().entrySet()) {
    
    
                    out.name(e.getKey());
                    write(out, e.getValue());
                }
                out.endObject();

            } else {
    
    
                throw new IllegalArgumentException("Couldn't write " + value.getClass());
            }
        }
    };

主要是递归调用了read方法将json串封装成JsonElement对象。

上面使用的JSON_ELEMENT只是TypeAdapter的其中一个实现类,下面让我们看看TypeAdapter这个抽象类。

该类的API对它的用法说明很清楚,简单的应用示例如下:

 Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
   new TypeAdapter<Foo>() {
    
    
     public Foo read(JsonReader in) throws IOException {
    
    
       if (in.peek() == JsonToken.NULL) {
    
    
         in.nextNull();
         return null;
       }
       // read a Foo from in and return it
     }
     public void write(JsonWriter out, Foo src) throws IOException {
    
    
       if (src == null) {
    
    
         out.nullValue();
         return;
       }
       // write src as JSON to out
     }
   }).create();

上面的使用示例都需要在read和write方法里进行非空判断,非常麻烦,有没有什么办法可以不写呢?当然有,TypeAdapter提供了一个优雅的解决方法:

 Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
   new TypeAdapter<Foo>() {
    
    
     public Foo read(JsonReader in) throws IOException {
    
    
       // read a Foo from in and return it
     }
     public void write(JsonWriter out, Foo src) throws IOException {
    
    
       // write src as JSON to out
     }
   }.nullSafe()).create();

看下nullSafe()方法:

public final TypeAdapter<T> nullSafe () {
    
    
            return new TypeAdapter<T>() {
    
    
                @Override
                public void write(JsonWriter out, T value) throws IOException {
    
    
                    if (value == null) {
    
    
                        out.nullValue();
                    } else {
    
    
                        TypeAdapter.this.write(out, value);
                    }
                }

                @Override
                public T read(JsonReader reader) throws IOException {
    
    
                    if (reader.peek() == JsonToken.NULL) {
    
    
                        reader.nextNull();
                        return null;
                    }
                    return TypeAdapter.this.read(reader);
                }
            };
        }

该方法就是把你的TypeAdapter对象包装了一个新的TypeAdapter对象。

在我们调用gson的fromJson(String json, Class<T> classOfT) 法的时候,最终会调用
fromJson(JsonReader reader, Type typeOfT)方法

/**
 * Reads the next JSON value from {@code reader} and convert it to an object
 * of type {@code typeOfT}. Returns {@code null}, if the {@code reader} is at EOF.
 * Since Type is not parameterized by T, this method is type unsafe and should be used carefully
 *
 * @throws JsonIOException if there was a problem writing to the Reader
 * @throws JsonSyntaxException if json is not a valid representation for an object of type
 */
@SuppressWarnings("unchecked")
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);
        //这里获取到的是自定义的TypeAdapter或者是Gson默认的ReflectiveTypeAdapterFactory.Adapter
        TypeAdapter<T> typeAdapter = getAdapter(typeToken);
        T object = typeAdapter.read(reader);
        return object;
    } 

	...
	
}

自定义的Adapter是怎么让Gson使用的,就是上面调用registerTypeAdapter方法进行注册的:

public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
    
    
   
   
   
    if (typeAdapter instanceof TypeAdapter<?>) {
    
    
    //根据自定义的TypeAdapter和传入的type封装成TypeAdapterFactory,并加入到factories中。
      factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter));
    }
    return this;
  }

然后调用GsonBuilder.create()方法创建Gson对象:

  /**
   * Creates a {@link Gson} instance based on the current configuration. This method is free of
   * side-effects to this {@code GsonBuilder} instance and hence can be called multiple times.
   *
   * @return an instance of Gson configured with the options currently set in this builder
   */
  public Gson create() {
    
    
    List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>(this.factories.size() + this.hierarchyFactories.size() + 3);
 //把GsonBuilder的factories传入到新定义的factories中,并交给新创建的Gson对象。
    factories.addAll(this.factories);
    Collections.reverse(factories);

    List<TypeAdapterFactory> hierarchyFactories = new ArrayList<TypeAdapterFactory>(this.hierarchyFactories);
    Collections.reverse(hierarchyFactories);
    factories.addAll(hierarchyFactories);

    addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories);

    return new Gson(excluder, fieldNamingPolicy, instanceCreators,
        serializeNulls, complexMapKeySerialization,
        generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient,
        serializeSpecialFloatingPointValues, longSerializationPolicy,
        datePattern, dateStyle, timeStyle,
        this.factories, this.hierarchyFactories, factories);
  }

TypeToken

Java的泛型在运行时会有类型擦除,Gson解析将得不到预期的类型,TypeToken就是解决这个问题的。解决方案就是:匿名类+反射。

//TypeToken.java


  /**
   * Constructs a new type literal. Derives represented class from type
   * parameter.
   *
   * <p>Clients create an empty anonymous subclass. Doing so embeds the type
   * parameter in the anonymous class's type hierarchy so we can reconstitute it
   * at runtime despite erasure.
   */
  @SuppressWarnings("unchecked")
  protected TypeToken() {
    
    
    this.type = getSuperclassTypeParameter(getClass());
    this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);
    this.hashCode = type.hashCode();
  }

  /**
   * Returns the type from super class's type parameter in {@link $Gson$Types#canonicalize
   * canonical form}.
   */
  static Type getSuperclassTypeParameter(Class<?> subclass) {
    
    
    Type superclass = subclass.getGenericSuperclass();
    if (superclass instanceof Class) {
    
    
      throw new RuntimeException("Missing type parameter.");
    }
    ParameterizedType parameterized = (ParameterizedType) superclass;
    return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
  }

其原理就是用一个继承TypeToken的匿名类,从而获取该匿名类的泛型超类,然后将该泛型超类强制转换为ParameterizedType。ParameterizedType包含了获取其实际类型参数的方法getActualTypeArguments()及获取其原始类型的方法getRawType()。

看下面这个例子:

public class TypeTokenTest {
    
    

    //待解析的json字符串: {"data":"data from server"}
    public class Response<T>{
    
    
        public T data;//简化数据, 省略了其他字段

        @Override
        public String toString() {
    
    
            return "Response{" +
                    "data=" + data +
                    '}';
        }
    }

    private Response<String> data;

    public static void main(String[] args) {
    
    
        String json = "{\"data\":\"data from server\"}";

        //fromJson(String json, Class<T> classOfT)的第二个参数classOfT期望获取Response<String>这种类型
        //Class responseClass = Response<String>.class; /但是这么写不能通过编译,因为Response<String>不是一个Class类型
        Class responseClass = Response.class; //只能这样获取类型, 但无法知道Response里面数据的类型

        Response<String> result = (Response<String>) new Gson().fromJson(json, responseClass);
        System.out.println("result=" + result);

        //Gson的解决方案
        Type type = new TypeToken<Response<String>>(){
    
    }.getType();
        System.out.println("type=" + type);//TypeTokenTest$Response<java.lang.String>
        result = new Gson().fromJson(json, type);
        System.out.println("result=" + result);

    }
}

new TypeToken<Response<String>>(){} 实例化过程可以分解如下:

1. 
class TypeToken$0 extends TypeToken<Response<String>>{
    
    
}
2.
TypeToken typeToken = new TypeToken$0();

TypeToken$0是TypeToken<Response<String>>的匿名子类。所以typeToken是TypeToken$0类型的,父类型是TypeToken<Response<String>>,而不是TypeToken<T>

所以上述getSuperclassTypeParameter()方法中

Type superclass = subclass.getGenericSuperclass();

得到的superclass 是TypeToken<Response<String>>,而不是TypeToken<T>。继续调用parameterized.getActualTypeArguments()[0] 得到的是Response<String>,这正是我们预期的类型。

这也是为什么TypeToken的构造方法是protected的,想要调用该类的public方法不能够直接new一个TypeToken对象,可以新建一个匿名类(new TypeToken(){})或者新建一个类继承TypeToken来得到这个类的实例,然后调用该类的public方法。

getAdapter()

//Gson.java


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

	  //遍历Gson的factories集合,其中自定义的TypeAdapter封装后的TypeAdapterFacotry也在里面。
      for (TypeAdapterFactory factory : factories) {
    
    
      	//调用TypeAdapterFacotry的create方法获取TypeAdapter
        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();
      }
    }
  }

到此为止TypeAdapter的工作方式已经说明了,现在总结一下:
1)通过GsonBuilder注册TypeAdapter,并把TypeAdapter封装成TypeAdpterFactory对象
2)将封装成的TypeAdapterFactory通过GsonBuilder的create方法传入Gson对象中
3)调用gson.fromJson方法,调用getAdapter方法返回自定义的Adapter,并调用其reader方法将json转为java对象

用两个图说明Adapter的工作原理
在这里插入图片描述
在这里插入图片描述

TypeAdapterFactory

前面分析了一下TypeAdapter的原理:先把TypeAdapter封装成TypeAdapterFactory,然后通过TypeAdapterFactory的create()方法创建TypeAdapter使用。在Gson中有大量的TypeAdapterFactory,比如基本类型都对应一个TypeAdapter,每个TypeAdapter都对应一个TypeAdapterFactory。

//TypeAdapters.java


/**
 * Type adapters for basic types.
 */
public final class TypeAdapters {
    
    

	public static final TypeAdapter<Boolean> BOOLEAN = new TypeAdapter<Boolean>() {
    
    
	    @Override
	    public Boolean read(JsonReader in) throws IOException {
    
    
	        JsonToken peek = in.peek();
	        if (peek == JsonToken.NULL) {
    
    
	            in.nextNull();
	            return null;
	        } else if (peek == JsonToken.STRING) {
    
    
	            // support strings for compatibility with GSON 1.7
	            return Boolean.parseBoolean(in.nextString());
	        }
	        return in.nextBoolean();
	    }
	    @Override
	    public void write(JsonWriter out, Boolean value) throws IOException {
    
    
	        out.value(value);
	    }
	};
        
	public static final TypeAdapterFactory BOOLEAN_FACTORY
      = newFactory(boolean.class, Boolean.class, BOOLEAN);


	...
  
}

我们注册的自定义TypeAdapter实际上就是先转换成TypeAdapterFactory然后在Gson的getAdapter方法中遍历TyperAdapterFactory,并调用create方法得到TypeAdapter。能不能直接传我们自定义的TypeAdapterFactory呢?答案是确定的,因为GsonBuilder提供了这个方法:

//GsonBuilder.java


  public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) {
    
    
    factories.add(factory);
    return this;
  }

其实在我们用new Gson()这个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对象的 factories 添加大量的Gson自带的TypeAdapterFactory:


...

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

上述添加TypeAdapterFactory的顺序是先添加 用户自定义的TypeAdapterFactory,然后添加
Gson自带的TypeAdapterFactory,最后添加ReflectiveTypeAdapterFactory。

Gson解析的时候也是根据这个顺序来获取TypeAdapterFactory的,详见getAdapter方法:

//Gson.java


  /**
   * Returns the type adapter for {@code} type.
   *
   * @throws IllegalArgumentException if this GSON cannot serialize and
   *     deserialize {@code type}.
   */
  @SuppressWarnings("unchecked")
  public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
    
    

	...

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

	...


}

getAdapter方法会遍历factories,根据type去获取TypeAdapterFactory,for循环中只要TypeAdapterFactory.create返回的TypeAdapter!=null 则返回创建的TypeAdapter,用该TypeAdapter解析json,因为用户自定义的TypeAdapterFactory和Gson自带的TypeAdapterFactory位置在factories中靠前,优先于ReflectiveTypeAdapterFactory遍历到,所以就避免了用Gson的反射机制来解析json了。

因此Gson的整体解析原理可以用如下图来概述:
在这里插入图片描述

用户自定义的TypeAdapterFactory(users’ type adapters)

就是用户自定义的各种TypeAdapterFactory或者是用户自定义的各种TypeAdapter对应的 TypeAdapterFactory。

Gson自带的TypeAdapterFactory

主要是系统的各种数据类型对应的TypeAdapterFactory。

ReflectiveTypeAdapterFactory

1)从factories中获取到ReflectiveTypeAdapterFactory对象
2)调用ReflectiveTypeAdapterFactory的create方法,返回一个ReflectiveTypeAdapterFactory.Adapter对象

//ReflectiveTypeAdapterFactory.java


/**
 * Type adapter that reflects over the fields and methods of a class.
 */
public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
    
    

	...  

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

	...  

}

ObjectConstructor
ObjectConstructor构造器对象用于Adapter在解析json时进行构造对象。而这个ObjectConstructor是来自于一个constructorConstructor的对象,ConstructorConstructor即构建构造器的意思,即用于创建ObjectConstructor构造器对象。

那么为什么需要一个ObjectConstructor构造器对象呢?你直接通过类型反射不就完成类型的构造?
原因是因为Gson是支持接口类型,比如List<?>这种集合类。而接口类型转化为Java的实际对象的方式主要有两种:
一种是常见的提供实现类
另一种是生成接口类型的动态代理。

而通过动态代理的方案明显不合适,因此Gson在处理接口类型的时候,默认提供了一些实现类。
constructorConstructor对象在ReflectiveTypeAdapterFactory构造的时候传入,

Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingPolicy,
      final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
      boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
      boolean prettyPrinting, boolean serializeSpecialFloatingPointValues,
      LongSerializationPolicy longSerializationPolicy,
      List<TypeAdapterFactory> typeAdapterFactories) {
    
    
    this.constructorConstructor = new ConstructorConstructor(instanceCreators);
...
}

constructorConstructor的构造,传入了一个instanceCreators对象,这个对象是一个享元对象。默认的情况下,这个对象为空,如果你有自己构造一个对象的需求,可以注入这个对象。那么,Gson会优先选择你注入的这个对象构造器来改造最终对象,我们来看下ConstructorConstructor的ObjectConstructor<T> get(TypeToken<T> typeToken)方法:

//ConstructorConstructor.java

 public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
    
    
        final Type type = typeToken.getType();
        final Class<? super T> rawType = typeToken.getRawType();

		//先通过type去获取InstanceCreator,如果获取到InstanceCreator,则通过它来创建构造器对象
        // first try an instance creator

        @SuppressWarnings("unchecked") // types must agree
        final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);
        if (typeCreator != null) {
    
    
            return new ObjectConstructor<T>() {
    
    
                @Override public T construct() {
    
    
                    return typeCreator.createInstance(type);
                }
            };
        }
			
		//再通过rawType去获取InstanceCreator,如果获取到InstanceCreator,则通过它来创建构造器对象
        // Next try raw type match for instance creators
        @SuppressWarnings("unchecked") // types must agree
        final InstanceCreator<T> rawTypeCreator =
                (InstanceCreator<T>) instanceCreators.get(rawType);
        if (rawTypeCreator != null) {
    
    
            return new ObjectConstructor<T>() {
    
    
                @Override public T construct() {
    
    
                    return rawTypeCreator.createInstance(type);
                }
            };
        }
		
		//如果是普通类,将使用newDefaultConstructor方法创建一个默认的构造器对象
        ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);
        if (defaultConstructor != null) {
    
    
            return defaultConstructor;
        }

		//如果是接口类,将通过newDefaultImplementationConstructor方法创建一个默认的构造器对象
        ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType);
        if (defaultImplementation != null) {
    
    
            return defaultImplementation;
        }

		//如果自定义的java类中没有默认构造器,那么最终会调用newUnsafeAllocator方法来为你创建对应的Java对象
        // finally try unsafe
        return newUnsafeAllocator(type, rawType);
    }


  private <T> ObjectConstructor<T> newDefaultConstructor(Class<? super T> rawType) {
    
    
    try {
    
    
     //此方法返回具有指定参数列表的构造函数对象,在这里没有传参数,即获取默认的构造器
      final Constructor<? super T> constructor = rawType.getDeclaredConstructor();
      if (!constructor.isAccessible()) {
    
    
        accessor.makeAccessible(constructor);
      }
      return new ObjectConstructor<T>() {
    
    
        @SuppressWarnings("unchecked") // T is the same raw type as is requested
        @Override public T construct() {
    
    
          try {
    
    
            Object[] args = null;
            return (T) constructor.newInstance(args);  //创建Java对象,并返回
          } catch (InstantiationException e) {
    
    
            // TODO: JsonParseException ?
            throw new RuntimeException("Failed to invoke " + constructor + " with no args", e);
          } catch (InvocationTargetException e) {
    
    
            // TODO: don't wrap if cause is unchecked!
            // TODO: JsonParseException ?
            throw new RuntimeException("Failed to invoke " + constructor + " with no args",
                e.getTargetException());
          } catch (IllegalAccessException e) {
    
    
            throw new AssertionError(e);
          }
        }
      };
    } catch (NoSuchMethodException e) {
    
    
      return null;
    }
  }

getBoundFields方法

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


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;
    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 {
    
    
        	//根据这个字段对应的Type获取对应的TypeAdapter,调用TypeAdapter的read读取fieldValue
            Object fieldValue = typeAdapter.read(reader);
            if (fieldValue != null || !isPrimitive) {
    
    
                field.set(value, fieldValue);//给field设置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
        }
        
    };
}

BoundField这个类的用途是将字段的名称和Field进行绑定,字段的名称可能是字段名或者是通过注解定义的名称。
比如有一个字段:

class Food {
    
    
	private String name;
}

这时会创建一个BoundField ,名称是"name"。

但是如果对此字段进行了注解,比如:

class Food {
    
    
	 @SerializedName(value = "myName1", alternate = "myName2")
	 private String name;
}

这时会创建两个BoundField ,一个名称是"myName1",另一个名称是"myName2",然后以"myName1"作为键,对应的BoundField作为值,另一个以"myName2"作为键,对应的BoundField作为值,存储在LinkedHashMap中。

对所有的Field创建出对应的BoundField后,像上述一样,将结果都保存在LinkedHashMap中,供后面Adpater解析json时使用。之后Adpater解析json时会根据解析出的name,去LinkedHashMap中获取对应的BoundField,然后调用BoundField的read方法读取value,并为Field设置该value。

3)通过Adpater的read方法不断读取json中的name,根据name去LinkedHashMap中获取对应的BoundField,然后调用BoundField的read方法读取value,并为Field设置该value(这个过程详见2) )。

//ReflectiveTypeAdapterFactory.java


        public static final class Adapter<T> extends TypeAdapter<T> {
    
    
            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();  //创建一个java对象

                try {
    
    
                    in.beginObject(); //开始读取一个JsonObject
                    while (in.hasNext()) {
    
    
                        String name = in.nextName();//获取name
                        //根据name获取对应的BoundField
                        BoundField field = boundFields.get(name);
                        if (field == null || !field.deserialized) {
    
    
                            in.skipValue();
                        } else {
    
    
                        	//调用BoundField的read方法读取value
                            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通过反射解析json ,核心原理简而言之就是通过反射创建Java对象,循环遍历该对象的Field,并通过Field的set(Object,value)方法来对Java对象的Field赋值。

步骤:
1)获取type对应的默认构造器
2)通过Constructor的newInstance()来创建一个type类型的Java对象
3)解析json的键值对,获取key和value,
4)获取key对应的Field,通过Field的set(Object, value)方法设置value

实例代码如下:

/**
 * Gson用到的反射原理
 */
public class GsonReflect {
    
    

    public static class Person {
    
    
        public String name;
        public String sex;

        public Person() {
    
    
        }

        public Person(String name, String sex) {
    
    
            this.name = name;
            this.sex = sex;
        }

        @Override
        public String toString() {
    
    
            return "Person{" +
                    "name='" + name + '\'' +
                    ", sex='" + sex + '\'' +
                    '}';
        }
    }


    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    
    

        //1.反射获取构造器,根据构造器创建Person对象
        Constructor<?> c = Person.class.getDeclaredConstructor();
        Person person = (Person) c.newInstance();
        System.out.println("person=" + person);

        //2.获取Person中的所有属性,为属性赋值
        Field[] fields = Person.class.getDeclaredFields();
        for (Field field : fields) {
    
    
            field.setAccessible(true);
            //获取属性名称
            String fieldName = field.getName();
            if(fieldName.equals("name")) {
    
    
                field.set(person, "孙悟空");
            } else if(fieldName.equals("sex")) {
    
    
                field.set(person, "男");
            }
        }
        System.out.println("person=" + person);
    }

}

上面的例子程序可以说是Gson中对json解析的简单雏形,当然Gson结合泛型做了大量的封装,使其可以通用。

JsonDeserializer的工作原理

Gson解析整体原理

参考:
JsonElement的简单说明
Gson反序列化详解
Gson之TypeAdapter的工作原理分析(1)
Gson之TypeAdapterFactory
Gson的反射解析机制详解(1)
Gson解析原理概述
Gson的反射解析机制详解(2)
Gson源码解析之InstanceCreator简单说明

Gson 的深度使用
Gson全解析(中)-TypeAdapter的使用
http://www.javacreed.com/gson-deserialiser-example/

Gson TypeAdapter Example

关于Gson的TypeToken

猜你喜欢

转载自blog.csdn.net/yzpbright/article/details/107597319