Gson是Google开发的Java API,用于转换Java对象和Json对象
Gson源码分析
Gson
Gson
的构造函数接收很多参数,Gson()
提供了一些默认的值
主要有两个方法toJson()
和fromJson()
toJson()
最终调用的是下面这个方法
public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
TypeAdapter adapter = this.getAdapter(TypeToken.get(typeOfSrc));
boolean oldLenient = writer.isLenient();
writer.setLenient(true);
boolean oldHtmlSafe = writer.isHtmlSafe();
writer.setHtmlSafe(this.htmlSafe);
boolean oldSerializeNulls = writer.getSerializeNulls();
writer.setSerializeNulls(this.serializeNulls);
try {
adapter.write(writer, src);
} catch (IOException var12) {
throw new JsonIOException(var12);
} finally {
writer.setLenient(oldLenient);
writer.setHtmlSafe(oldHtmlSafe);
writer.setSerializeNulls(oldSerializeNulls);
}
}
fromJson()
最终调用的是下面这个方法
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
boolean isEmpty = true;
boolean oldLenient = reader.isLenient();
reader.setLenient(true);
TypeAdapter typeAdapter;
try {
reader.peek();
isEmpty = false;
TypeToken e = TypeToken.get(typeOfT);
typeAdapter = this.getAdapter(e);
Object object = typeAdapter.read(reader);
Object var8 = object;
return var8;
} catch (EOFException var14) {
if(!isEmpty) {
throw new JsonSyntaxException(var14);
}
typeAdapter = null;
} catch (IllegalStateException var15) {
throw new JsonSyntaxException(var15);
} catch (IOException var16) {
throw new JsonSyntaxException(var16);
} finally {
reader.setLenient(oldLenient);
}
return typeAdapter;
}
都是通过TypeAdapter
的read()
和write()
完成
通过getAdapter()
方法获得对应类型的适配器
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
// 首先查找缓存,节省时间
TypeAdapter cached = (TypeAdapter)this.typeTokenCache.get(type);
if(cached != null) {
return cached;
} else {
// threadCalls是一个type-adapter表
Object threadCalls = (Map)this.calls.get();
boolean requiresThreadLocalCleanup = false;
if(threadCalls == null) {
threadCalls = new HashMap();
this.calls.set(threadCalls);
requiresThreadLocalCleanup = true;
}
// 从列表中拿到对应type的adapter
Gson.FutureTypeAdapter ongoingCall = (Gson.FutureTypeAdapter)((Map)threadCalls).get(type);
if(ongoingCall != null) {
return ongoingCall;
} else {
try {
// 没有就遍历工厂列表,创建一个合适的TypeAdapter
Gson.FutureTypeAdapter call = new Gson.FutureTypeAdapter();
((Map)threadCalls).put(type, call);
Iterator i$ = this.factories.iterator();
TypeAdapter candidate;
do {
if(!i$.hasNext()) {
throw new IllegalArgumentException("GSON cannot handle " + type);
}
TypeAdapterFactory factory = (TypeAdapterFactory)i$.next();
candidate = factory.create(this, type);
} while(candidate == null);
call.setDelegate(candidate);
this.typeTokenCache.put(type, candidate);
TypeAdapter var10 = candidate;
return var10;
} finally {
// 清理:从列表中移除这个type对应的adapter,为什么?
((Map)threadCalls).remove(type);
if(requiresThreadLocalCleanup) {
// 为何会在这里做移除?
this.calls.remove();
}
}
}
}
}
这个方法涉及到多线程的处理,不太易懂,使用了一个ThreadLocal
来存放Type-Adapter
列表
TypeAdapter
public abstract class TypeAdapter<T> {
public abstract void write(JsonWriter var1, T var2) throws IOException;
public abstract T read(JsonReader var1) throws IOException;
......
}
一个抽象的泛型类,用来执行序列化和反序列化,关键的方法是write()
和read()
这个东西和创建它的工厂基本是最重要的结构
public interface TypeAdapterFactory {
<T> TypeAdapter<T> create(Gson var1, TypeToken<T> var2);
}
工厂接口的create()
负责创建TypeAdapter
private final List<TypeAdapterFactory> factories;
Gson
类中有个工厂的列表,在构造函数中被添加很多的工厂
INTEGER = new TypeAdapter() {
public Number read(JsonReader in) throws IOException {
if(in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
} else {
try {
return Integer.valueOf(in.nextInt());
} catch (NumberFormatException var3) {
throw new JsonSyntaxException(var3);
}
}
}
public void write(JsonWriter out, Number value) throws IOException {
out.value(value);
}
};
INTEGER_FACTORY = newFactory(Integer.TYPE, Integer.class, INTEGER);
上面是解析int
的TypeAdapter
,里面是通过JsonReader
和JsonWriter
读写
JsonReader
public JsonReader(Reader in);
构造函数接收Reader
作为参数
public void beginObject() throws IOException {
int p = this.peeked;
if(p == 0) {
p = this.doPeek();
}
if(p == 1) {
this.push(3);
this.peeked = 0;
} else {
throw new IllegalStateException("Expected BEGIN_OBJECT but was " + this.peek() + " at line " + this.getLineNumber() + " column " + this.getColumnNumber());
}
}
标记对象的开始,提取,如果是对象开始,则进栈3(PEEKED_BEGIN_ARRAY
),如果不是则抛出异常
public void endObject() throws IOException {
int p = this.peeked;
if(p == 0) {
p = this.doPeek();
}
if(p == 2) {
--this.stackSize;
this.peeked = 0;
} else {
throw new IllegalStateException("Expected END_OBJECT but was " + this.peek() + " at line " + this.getLineNumber() + " column " + this.getColumnNumber());
}
}
标记对象的结束
public void beginArray() throws IOException {
int p = this.peeked;
if(p == 0) {
p = this.doPeek();
}
if(p == 3) {
this.push(1);
this.peeked = 0;
} else {
throw new IllegalStateException("Expected BEGIN_ARRAY but was " + this.peek() + " at line " + this.getLineNumber() + " column " + this.getColumnNumber());
}
}
标记数组的开始,提取,如果是数组开始,则进栈1(PEEKED_BEGIN_OBJECT
),如果不是则抛异常
public void endArray() throws IOException {
int p = this.peeked;
if(p == 0) {
p = this.doPeek();
}
if(p == 4) {
--this.stackSize;
this.peeked = 0;
} else {
throw new IllegalStateException("Expected END_ARRAY but was " + this.peek() + " at line " + this.getLineNumber() + " column " + this.getColumnNumber());
}
}
标记数组的结束
public boolean hasNext() throws IOException {
int p = this.peeked;
if(p == 0) {
p = this.doPeek();
}
return p != 2 && p != 4;
}
判断是否有下一个元素,如果不是对象结束和数组结束则有下一个元素,注意这里在提取后没有this.peeked = 0
,所以下一次操作不会再提取一次,而是使用取得的值
public String nextName() throws IOException {
int p = this.peeked;
if(p == 0) {
p = this.doPeek();
}
String result;
if(p == 14) { // PEEKED_UNQUOTED_NAME
result = this.nextUnquotedValue();
} else if(p == 12) { // PEEKED_SINGLE_QUOTED_NAME
result = this.nextQuotedValue('\'');
} else {
if(p != 13) { // PEEKED_DOUBLE_QUOTED_NAME
throw new IllegalStateException("Expected a name but was " + this.peek() + " at line " + this.getLineNumber() + " column " + this.getColumnNumber());
}
result = this.nextQuotedValue('\"');
}
this.peeked = 0;
return result;
}
下一个键,三种形式:无引号、单引号、双引号
然后是nextXX()
系列函数,读取下一个值,读取完成后会设置this.peeked = 0
复位
private int doPeek() throws IOException {
// 获得当前栈顶
int peekStack = this.stack[this.stackSize - 1];
int c;
if(peekStack == 1) { // PEEKED_BEGIN_OBJECT
// 再次进入切换为结束构造对象
this.stack[this.stackSize - 1] = 2; // PEEKED_END_OBJECT
} else if(peekStack == 2) { // PEEKED_END_OBJECT
c = this.nextNonWhitespace(true);
switch(c) {
case 44: // 逗号
break;
case 59: // 分号
this.checkLenient();
break;
case 93: // 右方括号
return this.peeked = 4; // PEEKED_END_ARRAY
default:
throw this.syntaxError("Unterminated array");
}
} else {
if(peekStack == 3 || peekStack == 5) { // PEEKED_BEGIN_ARRAY || PEEKED_TRUE
// 切换为结束数组
// 两种情况,一是目前是开始数组,二是完成一个键值对
this.stack[this.stackSize - 1] = 4; // PEEKED_END_ARRAY
// 完成键值对的情况,可能有更多键值对,可能就结束了
if(peekStack == 5) {
c = this.nextNonWhitespace(true);
switch(c) {
case 44: // 逗号
break;
case 59: // 分号
this.checkLenient();
break;
case 125: // 右大括号
return this.peeked = 2; // PEEKED_END_OBJECT
default:
throw this.syntaxError("Unterminated object");
}
}
c = this.nextNonWhitespace(true);
switch(c) {
case 34: // 双引号
return this.peeked = 13; // PEEKED_DOUBLE_QUOTED_NAME
case 39: // 单引号
this.checkLenient();
return this.peeked = 12; // PEEKED_SINGLE_QUOTED_NAME
case 125: // 右大括号
if(peekStack != 5) {
return this.peeked = 2; // PEEKED_END_OBJECT
}
throw this.syntaxError("Expected name");
default:
this.checkLenient();
--this.pos;
if(this.isLiteral((char)c)) {
return this.peeked = 14; // PEEKED_UNQUOTED_NAME
}
throw this.syntaxError("Expected name");
}
}
if(peekStack == 4) { // PEEKED_END_ARRAY
this.stack[this.stackSize - 1] = 5; // PEEKED_TRUE
c = this.nextNonWhitespace(true);
switch(c) {
case 58: // 冒号
break;
case 61: // 逗号
this.checkLenient();
if((this.pos < this.limit || this.fillBuffer(1)) && this.buffer[this.pos] == 62) {
++this.pos;
}
break;
default:
throw this.syntaxError("Expected \':\'");
}
} else if(peekStack == 6) { // PEEKED_FALSE
if(this.lenient) {
this.consumeNonExecutePrefix();
}
this.stack[this.stackSize - 1] = 7; // PEEKED_NULL
} else if(peekStack == 7) { // PEEKED_NULL
c = this.nextNonWhitespace(false);
if(c == -1) {
return this.peeked = 17; // PEEKED_EOF
}
this.checkLenient();
--this.pos;
} else if(peekStack == 8) { // PEEKED_SINGLE_QUOTED
throw new IllegalStateException("JsonReader is closed");
}
}
c = this.nextNonWhitespace(true);
switch(c) {
case 34: // 双引号
if(this.stackSize == 1) {
this.checkLenient();
}
return this.peeked = 9; // PEEKED_DOUBLE_QUOTED
case 39: // 单引号
this.checkLenient();
return this.peeked = 8; // PEEKED_SINGLE_QUOTED
case 91: // 左方括号
return this.peeked = 3; // PEEKED_BEGIN_ARRAY
case 93: // 右方括号
if(peekStack == 1) { // PEEKED_BEGIN_OBJECT
return this.peeked = 4; // PEEKED_END_ARRAY
}
case 44: // 逗号
case 59: // 分号
if(peekStack != 1 && peekStack != 2) { // PEEKED_BEGIN_OBJECT && PEEKED_END_OBJECT
throw this.syntaxError("Unexpected value");
}
this.checkLenient();
--this.pos;
return this.peeked = 7; // PEEKED_NULL
case 123: // 左大括号
return this.peeked = 1; // PEEKED_BEGIN_OBJECT
default:
--this.pos;
if(this.stackSize == 1) {
this.checkLenient();
}
int result = this.peekKeyword();
if(result != 0) {
return result;
} else {
result = this.peekNumber();
if(result != 0) {
return result;
} else if(!this.isLiteral(this.buffer[this.pos])) {
throw this.syntaxError("Expected value");
} else {
this.checkLenient();
return this.peeked = 10;
}
}
}
}
doPeek()
分为两个阶段,首先分析栈顶元素,栈顶元素指示了当前的分析阶段,然后如果前面没返回的话则继续分析下一个字符
beginObject
会给栈顶赋值PEEKED_BEGIN_ARRAY
,表示开始构造数组?
beginArray
会给栈顶赋值PEEKED_BEGIN_OBJECT
,表示开始构造对象?
流程比较难以理解,首先要了解stack
的确切意思
简单的字符串
带数组的字符串
JsonWriter
JsonWriter
就简单一些,主要是这些方法:
public JsonWriter beginArray() throws IOException;
public JsonWriter endArray() throws IOException;
public JsonWriter beginObject() throws IOException;
public JsonWriter endObject() throws IOException;
public JsonWriter name(String name) throws IOException;
public JsonWriter value(String value) throws IOException;
GsonBuilder
Gson
对象的构造器,可以自己进行配置,最终通过create()
获得Gson
对象
public GsonBuilder setVersion(double ignoreVersionsAfter);
忽略给定数字之后的版本号
public GsonBuilder excludeFieldsWithModifiers(int... modifiers);
忽略给定的限定符
public GsonBuilder excludeFieldsWithoutExposeAnnotation();
忽略不带Expose
注解的域
public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention);
public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy);
设置命名策略
public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies);
设置排除策略
public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy);
public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy);
对序列化和反序列化分别设置排除策略
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter);
注册类型适配器,可能是InstanceCreator
(这个东西在Gson
构造函数中提供给各个TypeAdapter
,具体干什么的不清楚)、JsonSerializer
、JsonDeserializer
、TypeAdapter
Excluder
这个类实现了TypeAdapterFactory
接口,可以做一些排除规则
可以设置版本号、限定符、是否处理内部类、要求暴露
Gson
的构造函数里设置了一个默认的Excluder
,也可以在GsonBuilder
中自己修改
factories.add(new ReflectiveTypeAdapterFactory(this.constructorConstructor, fieldNamingPolicy, excluder));
在构造函数中加入了TypeAdapter
工厂列表
明显ReflectiveTypeAdapterFactory
就是处理反射相关的东西
ReflectiveTypeAdapterFactory.BoundField field = (ReflectiveTypeAdapterFactory.BoundField)this.boundFields.get(e);
if(field != null && field.deserialized) {
field.read(in, instance);
} else {
in.skipValue();
}
上面是read()
中的一段,显然skip
了一些不想要的域
也有个接口ExclusionStrategy
,指定了需要跳过的域和类
public interface ExclusionStrategy {
boolean shouldSkipField(FieldAttributes var1);
boolean shouldSkipClass(Class<?> var1);
}
构造的时候可以提供排除策略
public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies);
调用了下面这个函数
public Excluder withExclusionStrategy(ExclusionStrategy exclusionStrategy, boolean serialization, boolean deserialization)
FieldNamingStrategy
名称映射策略
public interface FieldNamingStrategy {
String translateName(Field var1);
}
有一个实现的枚举FieldNamingPolicy
,提供了五种:
IDENTITY
UPPER_CAMEL_CASE
UPPER_CAMEL_CASE_WITH_SPACES
LOWER_CASE_WITH_UNDERSCORES
LOWER_CASE_WITH_DASHES
也是在ReflectiveTypeAdapterFactory
中被使用
private String getFieldName(Field f) {
SerializedName serializedName = (SerializedName)f.getAnnotation(SerializedName.class);
return serializedName == null?this.fieldNamingPolicy.translateName(f):serializedName.value();
}
可以看到,如果没有给出序列化的名字,就使用命名策略来处理,否则使用我们给出的名字