Gson源码解析
Gson使用方法:
Gson.fromJson(String json, Class clazz)
所以从 fromJson 开始解析
Gson.java
fromJson() 有多个重载函数,最终都会调用下面这个
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { boolean isEmpty = true; boolean oldLenient = reader.isLenient(); // lenient : 宽容
reader.setLenient(true); try {
reader.peek(); // 返回下一个标记 但不会消耗, 应该是为了看看是否抛出异常
isEmpty = false; // TypeToken 就是对 Type 的一个封装
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT); // 根据Type获取对应的 TypeToken
TypeAdapter<T> typeAdapter = getAdapter(typeToken); // 获取对应的 adapter
T object = typeAdapter.read(reader); return object;
} catch (EOFException e) { /*
* For compatibility with JSON 1.5 and earlier, we return null for empty
* documents instead of throwing.
*/
if (isEmpty) { return null;
} throw new JsonSyntaxException(e);
} catch (IllegalStateException e) { throw new JsonSyntaxException(e);
} catch (IOException e) { throw new JsonSyntaxException(e);
} finally {
reader.setLenient(oldLenient);
}
}
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) { // 省略部分代码
try {
FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
threadCalls.put(type, call); // 遍历所有的 TypeAdapterFactory ,找到匹配的 Adapter
// TypeAdapterFactory.create() 会返回对应的 TypeAdapter, 如果 TypeToken 不符合的话返回 null
for (TypeAdapterFactory factory : factories) {
TypeAdapter<T> candidate = factory.create(this, type); if (candidate != null) {
call.setDelegate(candidate);
typeTokenCache.put(type, candidate); return candidate;
}
} throw new IllegalArgumentException("GSON cannot handle " + type);
} finally {
threadCalls.remove(type); if (requiresThreadLocalCleanup) {
calls.remove();
}
}
}
上面 getAdapter 代码中会遍历存储 TypeAdapterFactory 的 factories 来找匹配的 TypeAdapter
那 factories 是什么时候添加的?
Gson( ... 省略参数 ... ) { // 省略部分代码
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); // 添加用户自定义的 typeadapter
factories.addAll(typeAdapterFactories); // 添加基本类型的 tpyeAdatper
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); // 后面还有很多,此处省略 ...
// type adapters for composite and user-defined types
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
factories.add(new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor));
factories.add(TypeAdapters.ENUM_FACTORY); // 用于反射的 typeAdapter
factories.add(new ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingStrategy, excluder)); this.factories = Collections.unmodifiableList(factories);
}
我们再回到 fromJson() 中,刚才分析到了 getAdapter()
接下来继续
T object = typeAdapter.read(reader);
找到匹配的 typeAdapter 就会调用其 read() 函数进行解析,此处我们着重分析 Gson 的反射实现原理,所以此处查看 ReflectiveTypeAdapterFactory 中 adapter 的 read() 实现
ReflectiveTypeAdapterFactory.java
在 ReflectiveTypeAdapterFactory 中有内部类 Adapter 如下,真正调用的是其 read() 函数
public static final class Adapter<T> extends TypeAdapter<T> { @Override public T read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) {
in.nextNull(); return null;
}
T instance = constructor.construct(); // 反射创建实例
try {
in.beginObject(); // 开始读Object,会设置 stack\[stackSize ++\] = JsonScope.EMPTY_OBJECT 后面 in.doPeek() 会用到
while (in.hasNext()) { // 调用 doPeek()
String name = in.nextName(); // 获取变量名
BoundField field = boundFields.get(name); if (field == null || !field.deserialized) {
in.skipValue();
} else {
field.read(in, instance); // 给变量设值 调用 field.set() 设值 其中会调用 adapter.read() 递归
}
}
} catch (...) { // 省略代码
}
in.endObject(); return instance; // 返回解析到的对象实例
}
}
至此整体大概的解析完成,总结一下整体流程,附上流程图
最后介绍一些比较重要的函数
上述代码中的 in.beginObject() in.hasNext() in.nextName() in.skipValue() 都会调用 Reader 中的 doPeek(),其他的代码也会调用 doPeek() 所以这个函数非常重要,接下来解析此函数
JsonReader.java
-
doPeek()
int doPeek() throws IOException { // 每次调用 beginXXX 的时候都会调用 stack\[stackSize ++\] = JsonScope.XXX int peekStack = stack\[stackSize - 1\]; // 获取 stack 顶部标志 if (peekStack == JsonScope.EMPTY_ARRAY) { stack\[stackSize - 1\] = JsonScope.NONEMPTY_ARRAY; } else if (peekStack == JsonScope.NONEMPTY_ARRAY) { int c = nextNonWhitespace(true); // 获取下一个非空字符 switch (c) { // 解析字符,下面的代码和这个类似,就省略了 case '\]': return peeked = PEEKED_END_ARRAY; case ';': checkLenient(); // fall-through case ',': break; default: throw syntaxError("Unterminated array"); } } else if ( ... ) { // ... } int c = nextNonWhitespace(true); switch (c) { // ... } int result = peekKeyword(); if (result != PEEKED_NONE) { return result; } result = peekNumber(); if (result != PEEKED_NONE) { return result; } return peeked = PEEKED_UNQUOTED; }
peek() 函数内部基本上是对 doPeek() 的调用
JsonReader.java
-
nextNonWhitespace()
private int nextNonWhitespace(boolean throwOnEof) throws IOException { char\[\] buffer = this.buffer; int p = pos; // pos 表示当前解析的位置 int l = limit; // limit 表示最后位置 while (true) { if (p == l) { // 说明 buffer 已经读完了 pos = p; if (!fillBuffer(1)) { // 从 instream 中填充 buffer, 参数表示最少需要填充多少, 返回表示是否能满足最少需要的 break; } p = pos; // 更新数据 l = limit; } int c = buffer\[p++\]; // 获取当前字符 if (c == 'n') { lineNumber++; lineStart = p; // 当前行从哪个位置开始 continue; } else if (c == ' ' || c == 'r' || c == 't') { // 过滤空格等字符 continue; } if (c == '/') { // 读取 /**/ 和 // 的注释 pos = p; if (p == l) { pos--; // push back '/' so it's still in the buffer when this method returns boolean charsLoaded = fillBuffer(2); pos++; // consume the '/' again if (!charsLoaded) { return c; } } checkLenient(); // 检测兼容性,先忽略 char peek = buffer\[pos\]; switch (peek) { case '*': // 读取 "/**/" 注释 pos++; if (!skipTo("*/")) { throw syntaxError("Unterminated comment"); } p = pos + 2; l = limit; continue; case '/': // 读取 "//" 注释 // skip a // end-of-line comment pos++; skipToEndOfLine(); p = pos; l = limit; continue; default: return c; } } else if (c == '#') { // 读取 '#' 的注释, 直接跳到下一行 pos = p; checkLenient(); skipToEndOfLine(); p = pos; l = limit; } else { // 返回解析到的字符,并重置pos pos = p; return c; } } if (throwOnEof) { throw new EOFException("End of input" + " at line " + getLineNumber() + " column " + getColumnNumber()); } else { return -1; } }
在 nextNonWhitespace 中会调用到 fillBuffer() 来填充,接下来看一下 fillBuffer() 的实现
private boolean fillBuffer(int minimum) throws IOException { char\[\] buffer = this.buffer;
lineStart -= pos; if (limit != pos) {
limit -= pos;
System.arraycopy(buffer, pos, buffer, 0, limit); // 覆盖之前解析过的字符
} else {
limit = 0;
}
pos = 0; int total; while ((total = in.read(buffer, limit, buffer.length - limit)) != -1) {
// 从 reader 中读取字符填满 buffer
limit += total; // 如果是第一次读取的话,要保证首个字符不是非法字符
if (lineNumber == 0 && lineStart == 0 && limit > 0 && buffer\[0\] == 'ufeff') {
pos++;
lineStart++;
minimum++;
} if (limit >= minimum) { // 可以满足需求的字符数量
return true;
}
} return false;
}
这样 Gson 使用反射来解析 json 大体上解析完了,接下来自己实现了一个简单的Json解析器,地址如下:Json解析器