Gson源码解析

Gson使用方法:
Gson.fromJson(String json, Class clazz)
所以从 fromJson 开始解析

Gson.java

fromJson() 有多个重载函数,最终都会调用下面这个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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 是什么时候添加的?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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()
接下来继续

1
T object = typeAdapter.read(reader);

找到匹配的 typeAdapter 就会调用其 read() 函数进行解析,此处我们着重分析 Gson 的反射实现原理,所以此处查看 ReflectiveTypeAdapterFactory 中 adapter 的 read() 实现

ReflectiveTypeAdapterFactory.java

在 ReflectiveTypeAdapterFactory 中有内部类 Adapter 如下,真正调用的是其 read() 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    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()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    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() 的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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解析器

热评文章