官网地址: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/