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解析器,地址如下:https://github.com/5A59/JsonParser