上面我们学习了gson 的序列化过程方法 toJson 的源码,相信对很多的流程有了一个了解,紧接着我们来学习下gson反序列化过程,fromJson .还是老样子,代码一点一点看。
我们先模拟一个反序列化过程
String json="{\"age\":30,\"name\":\"明\",\"len\":170]}"; TestMode jsTestMode=gson.fromJson(json,TestMode.class);
public class TestMode {
@Expose(deserialize = true)
private int age;
@Expose(serialize = false, deserialize = true)
String name;
@Expose(deserialize = true)
@SerializedName("len")
int length;
// public List<TestMode> getTestMode() {
// return testMode;
// }
//
// public void setTestMode(List<TestMode> testMode) {
// this.testMode = testMode;
// }
//
// List<TestMode> testMode;
public TestMode(){
}
public TestMode(int age, String name, int length) {
this.age = age;
this.name = name;
this.length = length;
}
public int getLength() {
return length;
}
public void setLength(int length) {
this.length = length;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "TestMode{" +
"age=" + age +
", name='" + name + '\'' +
", length=" + length +
// ", testMode=" + testMode +
'}';
}
}
//classofT 就 是我们要将json 字符串反序列位的对象的.class 类
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
//生成一个object对象 ,class 转为type接口类型,因为class<T> 本身实现了type接口
Object object = fromJson(json, (Type) classOfT);
//将object 转为 具体的类对象并返回
return Primitives.wrap(classOfT).cast(object);
}
//
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
if (json == null) {
return null;
}
// 将json 字符串封装到StringReader 类中 StringReader继承自Reader 类 用来处理流相关字符串。
StringReader reader = new StringReader(json);
T target = (T) fromJson(reader, typeOfT);
return target;
}
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
对字符串流做一个封装,放入jsonReader中,同时,jsonReader 也是反序列的关键类,基本所有的字符到对象的具体的操作逻辑都是由它来实现的
JsonReader jsonReader = newJsonReader(json);
T object = (T) fromJson(jsonReader, typeOfT);
//在整个反序列化过程结束之前效验 jsonReader 的 peeked 的状态
//如果 peeker 未处于结束状态,则会报错
assertFullConsumption(object, jsonReader);
return object;
}
前面是一些准备的gromJson 构造函数,下面看主要部分
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
boolean isEmpty = true;
// 接受不符合规定的json变量的值
boolean oldLenient = reader.isLenient();
//强制设置为接受
reader.setLenient(true);
try {
//此处相当于调用了一次 JsonReader 中的 doPeek() 方法,返回下一个令牌的类型而不消耗它,设置当前令牌
reader.peek();
isEmpty = false;
//TypeToken 本质上是 Class 的增强封装类
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
//根据要转化的实体类型,获取相应的适配器
TypeAdapter<T> typeAdapter = getAdapter(typeToken);
//通过适配器生成实体类
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) {
// TODO(inder): Figure out whether it is indeed right to rethrow this as JsonSyntaxException
throw new JsonSyntaxException(e);
} catch (AssertionError e) {
AssertionError error = new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage());
error.initCause(e);
throw error;
} finally {
reader.setLenient(oldLenient);
}
}
主要看下 getAdapter 方法
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
//TypeToken<T> 类字面翻译是类型令牌,其实就是保存了这个类的属性,类型和hashcode等值为后期操作准备
//typeTokenCache 内部是一个线程安全的ConcurrentHashMap ,它主要用来缓存类型令牌,如果能够获取到值,那说明之前已经有了相同的类型令牌,也就是说是同一个,如果有了就直接返回
TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
//calls 是一个 ThreadLocal 对象 ,当前线程中保存一份缓存,里面存入的对象会在 finally 代码块中清空掉
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);
//factories 是适配器集合工厂,通过遍历找到相关类型
for (TypeAdapterFactory factory : factories) {
//根据上边我们的实体类 type可以判断最终执行 ReflectiveTypeAdapterFactory 的create方法返回值不为空,所以他的适配器类型是这样确定的 ,如果不算自定义是41种适配器,当然,方法对于不是对应类型的参数会返回 null,所以不为空说明找到了对应的适配器类型。
//完整的适配器包括它类本身的适配器类型,还包括它所有变量的适配器类型,call存储的就是这样的数据,因为create 执行后,会通过反射获取到所有类中变量名称,并且通过getAdapter 也就是当前方法获取类型,这是如果之前已经有这个适配器存储了,就直接返回了ongoingCall
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 {
//清除 ThreadLocal 缓存
threadCalls.remove(type);
if (requiresThreadLocalCleanup) {
calls.remove();
}
}
}
这里返回了该类对应的适配器类型。并且对应变量也会调用到这个方法来获取变量的适配器类型。
typeAdapter.read(reader); 是适配器中的read 方法,不同的类对应的适配器是不同的
所有的适配器类都实现了TypeAdapterFactory 适配器工厂接口, 重写了create 方法,而create 的返回值是一个adapter类,所有的adapter 都继承 TypeAdapter<T> 并且实现了其中的抽象方法read 和write。我们的TestMode 对应的是 ReflectiveTypeAdapterFactory
factories.add(TypeAdapters.INET_ADDRESS_FACTORY); 这个是基本类型等的适配器 是TypeAdapters ,例如bool string 等
直接看ReflectiveTypeAdapterFactory的create
@Override public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
Class<? super T> raw = type.getRawType();
//这里用于比对类型,如果不是相应的类型就返回null
//确定此* {@code Class}对象表示的类或接口是否与指定的{{code code}}参数所表示的类或接口相同,或者是该类或接口的超类或父接口。 。如果是,则返回{@code true}; *否则返回{@code false}
//很显然,这里返回的是true 应为我们的类是TestMode 是一个class类
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));
}
然后看下adapter 构造方法
getBoundFields 方法就是通过反射获取所有变量属性 Map<String, BoundField> result = new LinkedHashMap<String, BoundField>(); key 对应的是字段名,BoundField 是对该字段的属性的保存。
static abstract class BoundField {
final String name;
final boolean serialized;
final boolean deserialized;
protected BoundField(String name, boolean serialized, boolean deserialized) {
this.name = name;
this.serialized = serialized;
this.deserialized = deserialized;
}
abstract boolean writeField(Object value) throws IOException, IllegalAccessException;
abstract void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException;
abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException;
}
现在回到typeAdapter.read 方法 while 循环执行,直到反序列化结束。
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;
}
//创建一个实例化对象 就是 TestMode
T instance = constructor.construct();
try {
//开始反序列化前的准备
in.beginObject();
//是否还有下一个,没有返回false 有返回true 并设置指令
while (in.hasNext()) {
//获取json 中的一个key
String name = in.nextName();
//通过key 找到对应的属性对象
BoundField field = boundFields.get(name);
if (field == null || !field.deserialized) {
in.skipValue();
} else {
//开始读入
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 {...}
}
我们之前做的所有的准备工作都会在这个类中提现出来。字符传中提取key 并获取到field ,然后执行field 的read 方法,BoundField 重写read 方法
@Override void read(JsonReader reader, Object value)
throws IOException, IllegalAccessException {
//根据json字符串和适配器,读取当前field 的value 值
Object fieldValue = typeAdapter.read(reader);
if (fieldValue != null || !isPrimitive) {
//根据field (key 对应的field)设置值到value (TestDoem) 中 fieldValue (对象值)
field.set(value, fieldValue);
}
}
到这里整个流程就结束了,下面我们来看前面的几个具体操作类
doPeek()
//JsonReader.class
int doPeek() throws IOException {
//stack 是一个定义在 JsonReader 中的 int 数组,作为 JsonReader 的指令集存在,用于控制变量 peeked 的状态
//在 JsonReader 初始化的时候会将 stack 的第一个元素变成6,其余均为0
//6的意思根据官方注释为 "No object or array has been started"(还没开始读取对象或列表)
//6作为常量保存在 JsonScope 中,JsonScope 中还保存了很多代表指令的常量,下列会用到
//stackSize 是 stack 的有效元素计数器,初始化时 stackSize = 1,即只有第一个元素是有效的
int peekStack = stack[stackSize - 1];
//JsonScope.EMPTY_ARRAY = 1
if (peekStack == JsonScope.EMPTY_ARRAY) {
//JsonScope.NONEMPTY_ARRAY = 2
stack[stackSize - 1] = JsonScope.NONEMPTY_ARRAY;
} else if (peekStack == JsonScope.NONEMPTY_ARRAY) {
//在第一次调用 nextNonWhitespace(true) 方法的时候,json 字符串会被转存为一个 char 数组
//该方法以 int 值的形式返回下一个要解析的 char 对象
int c = nextNonWhitespace(true);
switch (c) {
case ']':
//peeked 是 JsonReader 中最重要的用来状态控制的 int 变量
//peeker 和 stack 会协同控制 JsonReader 的逻辑行为
return peeked = PEEKED_END_ARRAY; //PEEKED_END_ARRAY = 4
case ';':
//检查标准协议选项,json 标准中的符号没有分号
//所以在 lenient = false 的时候就会报错
checkLenient();
case ',':
break;
default:
throw syntaxError("Unterminated array");
}
//JsonScope.EMPTY_OBJECT = 3,JsonScope.NONEMPTY_OBJECT = 5
} else if (peekStack == JsonScope.EMPTY_OBJECT || peekStack == JsonScope.NONEMPTY_OBJECT) {
//JsonScope.DANGLING_NAME = 4
stack[stackSize - 1] = JsonScope.DANGLING_NAME;
if (peekStack == JsonScope.NONEMPTY_OBJECT) {
int c = nextNonWhitespace(true);
switch (c) {
case '}':
return peeked = PEEKED_END_OBJECT; //PEEKED_END_OBJECT = 2
case ';':
checkLenient();
case ',':
break;
default:
throw syntaxError("Unterminated object");
}
}
int c = nextNonWhitespace(true);
switch (c) {
case '"':
return peeked = PEEKED_DOUBLE_QUOTED_NAME; //PEEKED_DOUBLE_QUOTED_NAME = 13
case '\'':
checkLenient();
return peeked = PEEKED_SINGLE_QUOTED_NAME; //PEEKED_SINGLE_QUOTED_NAME = 12
case '}':
if (peekStack != JsonScope.NONEMPTY_OBJECT) {
return peeked = PEEKED_END_OBJECT;
} else {
throw syntaxError("Expected name");
}
default:
checkLenient();
pos--;
if (isLiteral((char) c)) {
return peeked = PEEKED_UNQUOTED_NAME; //PEEKED_UNQUOTED_NAME = 14
} else {
throw syntaxError("Expected name");
}
}
} else if (peekStack == JsonScope.DANGLING_NAME) {
stack[stackSize - 1] = JsonScope.NONEMPTY_OBJECT;
int c = nextNonWhitespace(true);
switch (c) {
case ':':
break;
case '=':
checkLenient();
//buffer 是储存 json 字符串的 char 数组
//pos 是已经读取到字符的数量指针
//limit 是 buffer 的可用部分的总长
if ((pos < limit || fillBuffer(1)) && buffer[pos] == '>') {
pos++;
}
break;
default:
throw syntaxError("Expected ':'");
}
//JsonScope.EMPTY_DOCUMENT = 6
//第一次进入方法的时候,会进入这个 if 语句中
} else if (peekStack == JsonScope.EMPTY_DOCUMENT) {
//检查标准化协议相关
if (lenient) {
consumeNonExecutePrefix();
}
//JsonScope.NONEMPTY_DOCUMENT = 7
stack[stackSize - 1] = JsonScope.NONEMPTY_DOCUMENT;
} else if (peekStack == JsonScope.NONEMPTY_DOCUMENT) {
int c = nextNonWhitespace(false);
if (c == -1) {
return peeked = PEEKED_EOF;
} else {
checkLenient();
pos--;
}
//JsonScope.CLOSED = 8
} else if (peekStack == JsonScope.CLOSED) {
throw new IllegalStateException("JsonReader is closed");
}
//在这里获取到了下一个要解析的 char 的 int 值
int c = nextNonWhitespace(true);
//进入 switch 去进行定位,定位到了之后修改 peeked 的状态
switch (c) {
case ']':
if (peekStack == JsonScope.EMPTY_ARRAY) {
return peeked = PEEKED_END_ARRAY;
}
case ';':
case ',':
if (peekStack == JsonScope.EMPTY_ARRAY || peekStack == JsonScope.NONEMPTY_ARRAY) {
checkLenient();
pos--;
return peeked = PEEKED_NULL;
} else {
throw syntaxError("Unexpected value");
}
case '\'':
checkLenient();
return peeked = PEEKED_SINGLE_QUOTED;
case '"':
return peeked = PEEKED_DOUBLE_QUOTED;
case '[':
return peeked = PEEKED_BEGIN_ARRAY;
case '{':
return peeked = PEEKED_BEGIN_OBJECT;
default:
pos--;
}
//peekKeyword() 方法会从 buffer 数组里获取下一个 char
//然后根据这个字符判断下一个要处理的字符串是不是 true、false、null 等特殊字符
//如果不是,会返回 result = PEEKED_NONE
int result = peekKeyword();
if (result != PEEKED_NONE) {
//不等于 PEEKED_NONE,证明下一个确实是特殊字符
return result;
}
//peekNumber() 方法和上述 peekKeyword() 方法很类似
//用于判断下一个要处理的字符串是否是数字
result = peekNumber();
if (result != PEEKED_NONE) {
return result;
}
//isLiteral(buffer[pos]) 用于判断下一个字符是否是特殊符
//比如 换行符、井号、括号 等
//如果是 换行符 的话这里就会抛出错误
if (!isLiteral(buffer[pos])) {
throw syntaxError("Expected value");
}
checkLenient();
return peeked = PEEKED_UNQUOTED; //PEEKED_UNQUOTED = 10
}
beginObject()
public void beginObject() throws IOException {
int p = peeked;
//初始化时 peeked = PEEKED_NONE
//在 doPeek() 方法中会修改成 PEEKED_BEGIN_OBJECT,即开始一个 Object 的序列化
if (p == PEEKED_NONE) {
p = doPeek();
}
if (p == PEEKED_BEGIN_OBJECT) {
//push(...) 方法会检查 stack 数组的容积,适时进行扩容,并把传入的指令存放到数组中
//此处将 EMPTY_OBJECT 指令存入到 stack 中
push(JsonScope.EMPTY_OBJECT);
//将 peeked 状态初始化
peeked = PEEKED_NONE;
} else {
throw new IllegalStateException("Expected BEGIN_OBJECT but was " + peek() + locationString());
}
}
nextName()
public String nextName() throws IOException {
//老样子进行 peeked 的状态获取
int p = peeked;
if (p == PEEKED_NONE) {
p = doPeek();
}
String result;
//在这里通过 if 语句和 peeked 定位 json 的 key 是用单引号还是双引号包裹的
//result 就是 key 的字符串
if (p == PEEKED_UNQUOTED_NAME) {
result = nextUnquotedValue();
} else if (p == PEEKED_SINGLE_QUOTED_NAME) {
result = nextQuotedValue('\'');
} else if (p == PEEKED_DOUBLE_QUOTED_NAME) {
result = nextQuotedValue('"');
} else {
throw new IllegalStateException("Expected a name but was " + peek() + locationString());
}
//将 peeked 状态初始化
peeked = PEEKED_NONE;
//pathNames 是一个用来储存所有 key 的字符串的数组
pathNames[stackSize - 1] = result;
return result;
}
到此反序列化源码学习完成了。
参考:
https://segmentfault.com/a/1190000017868423?utm_source=tag-newest
https://www.jianshu.com/p/da21b3a59b47