Gson 是开发中我们经常使用的一款json 解析框架,也是Google 推出的诸多良品之一,今天我们就从源码的角度看下gson 是如何来做序列化的,即如何通过toJson方法来做序列化的。
首先是获取Gson对象,只是Gson提供的对外方法类,有两种方式获取Gson对象,大概了解下。
GsonBuilder gsonBuilder=new GsonBuilder();
Gson BuGson=gsonBuilder.create();
Gson gson = new Gson();
序列化大概的步骤:
1.将类对象获取适配器对象
2.通过反射机制获取对象的方法名字段和值
3.通过流将每个字段对应的键和值逐个写入拼接
4.输出序列化后的json 字符串
因为Gson本身有多种适配器类型,就找了一个比较有代表性的类型适配器
ReflectiveTypeAdapterFactory 类
为了更好理解,先来个实体类,他对应的ReflectiveTypeAdapterFactory 适配器,字段中的注解暂时忽略
public class TestMode {
@Expose(deserialize = true)
private int age;
@Expose(serialize = false, deserialize = true)
String name;
@Expose(deserialize = true)
@SerializedName("len")
int length;
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 +
'}';
}
}
两种初始化Gson都可以,今天就不说他俩的区别了,后边会再出一篇具体讲GsonBuilder 使用,直接看Gson 构造函数
public Gson() {
this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY,
Collections.<Type, InstanceCreator<?>>emptyMap(), DEFAULT_SERIALIZE_NULLS,
DEFAULT_COMPLEX_MAP_KEYS, DEFAULT_JSON_NON_EXECUTABLE, DEFAULT_ESCAPE_HTML,
DEFAULT_PRETTY_PRINT, DEFAULT_LENIENT, DEFAULT_SPECIALIZE_FLOAT_VALUES,
LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT, DateFormat.DEFAULT,
Collections.<TypeAdapterFactory>emptyList(), Collections.<TypeAdapterFactory>emptyList(),
Collections.<TypeAdapterFactory>emptyList());
}
Gson(Excluder excluder, FieldNamingStrategy fieldNamingStrategy,
Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
int timeStyle, List<TypeAdapterFactory> builderFactories,
List<TypeAdapterFactory> builderHierarchyFactories,
List<TypeAdapterFactory> factoriesToBeAdded) {
this.excluder = excluder;
this.fieldNamingStrategy = fieldNamingStrategy;
this.instanceCreators = instanceCreators;
this.constructorConstructor = new ConstructorConstructor(instanceCreators);
this.serializeNulls = serializeNulls;
this.complexMapKeySerialization = complexMapKeySerialization;
this.generateNonExecutableJson = generateNonExecutableGson;
this.htmlSafe = htmlSafe;
this.prettyPrinting = prettyPrinting;
this.lenient = lenient;
this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
this.longSerializationPolicy = longSerializationPolicy;
this.datePattern = datePattern;
this.dateStyle = dateStyle;
this.timeStyle = timeStyle;
this.builderFactories = builderFactories;
this.builderHierarchyFactories = builderHierarchyFactories;
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);
// users' type adapters
factories.addAll(factoriesToBeAdded);
// type adapters for basic platform types
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);
TypeAdapter<Number> longAdapter = longAdapter(longSerializationPolicy);
factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter));
factories.add(TypeAdapters.newFactory(double.class, Double.class,
doubleAdapter(serializeSpecialFloatingPointValues)));
factories.add(TypeAdapters.newFactory(float.class, Float.class,
floatAdapter(serializeSpecialFloatingPointValues)));
factories.add(TypeAdapters.NUMBER_FACTORY);
factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY);
factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY);
factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter)));
factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter)));
factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY);
factories.add(TypeAdapters.CHARACTER_FACTORY);
factories.add(TypeAdapters.STRING_BUILDER_FACTORY);
factories.add(TypeAdapters.STRING_BUFFER_FACTORY);
factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));
factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));
factories.add(TypeAdapters.URL_FACTORY);
factories.add(TypeAdapters.URI_FACTORY);
factories.add(TypeAdapters.UUID_FACTORY);
factories.add(TypeAdapters.CURRENCY_FACTORY);
factories.add(TypeAdapters.LOCALE_FACTORY);
factories.add(TypeAdapters.INET_ADDRESS_FACTORY);
factories.add(TypeAdapters.BIT_SET_FACTORY);
factories.add(DateTypeAdapter.FACTORY);
factories.add(TypeAdapters.CALENDAR_FACTORY);
factories.add(TimeTypeAdapter.FACTORY);
factories.add(SqlDateTypeAdapter.FACTORY);
factories.add(TypeAdapters.TIMESTAMP_FACTORY);
factories.add(ArrayTypeAdapter.FACTORY);
factories.add(TypeAdapters.CLASS_FACTORY);
// type adapters for composite and user-defined types
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
factories.add(jsonAdapterFactory);
factories.add(TypeAdapters.ENUM_FACTORY);
factories.add(new ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
this.factories = Collections.unmodifiableList(factories);
}
主要是做了一些数据的初始化以及适配器的添加工作,现在来看toJson()方法
public String toJson(Object src) {
if (src == null) {
//返回一个null 字串
return toJson(JsonNull.INSTANCE);
}
return toJson(src, src.getClass());
}
public String toJson(Object src, Type typeOfSrc) {
//创建字符串编辑器,继承自writer,内部就是StringBuffer 和一个写入锁,后边的字段会写入他里边然后toString 出来。
StringWriter writer = new StringWriter();
toJson(src, typeOfSrc, writer);
return writer.toString();
}
public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {
try {
//操作字串拼接的核心类,它确定了字段间是如何拼接的
JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
toJson(src, typeOfSrc, jsonWriter);
} catch (IOException e) {
throw new JsonIOException(e);
}
}
//最终调用方法,方法执行完成后整个序列化基本就完成了。
public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc));
boolean oldLenient = writer.isLenient();
writer.setLenient(true);
boolean oldHtmlSafe = writer.isHtmlSafe();
writer.setHtmlSafe(htmlSafe);
boolean oldSerializeNulls = writer.getSerializeNulls();
writer.setSerializeNulls(serializeNulls);
try {
((TypeAdapter<Object>) adapter).write(writer, src);
} catch (IOException e) {
throw new JsonIOException(e);
} catch (AssertionError e) {
AssertionError error = new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage());
error.initCause(e);
throw error;
} finally {
writer.setLenient(oldLenient);
writer.setHtmlSafe(oldHtmlSafe);
writer.setSerializeNulls(oldSerializeNulls);
}
}
其实主要有两个地方。
1.TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc));
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;
}
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
//键和值类型参数始终一致 这个目前没搞明白要干啥,唯一觉得可行的就是并发访问时可能出现这种onfoingCal不为空,有待近一步理解
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种适配器
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 {
threadCalls.remove(type);
if (requiresThreadLocalCleanup) {
calls.remove();
}
}
}
进入ReflectiveTypeAdapterFactory看下 create干了什么事
@Override public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
Class<? super T> raw = type.getRawType();
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));
}
接着看 getBoundFields 函数,所有的反射操作都是在它里边完成的
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {
//有序的hashMap 用于存储反射获取的接口声明的字段
Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
if (raw.isInterface()) {
return result;
}
Type declaredType = type.getType();
while (raw != Object.class) {
//反射获取所有字段field集合
Field[] fields = raw.getDeclaredFields();
for (Field field : fields) {
//提取注解数值
boolean serialize = excludeField(field, true);
boolean deserialize = excludeField(field, false);
if (!serialize && !deserialize) {
continue;
}
//类中的成员变量为private,故必须进行此操作 设置权限 调用的是 setAccessible
accessor.makeAccessible(field);
//获取当前field字段函数类型
Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
//变量名称 例如 name. 集合中只有一个值
List<String> fieldNames = getFieldNames(field);
BoundField previous = null;
for (int i = 0, size = fieldNames.size(); i < size; ++i) {
String name = fieldNames.get(i);
if (i != 0) serialize = false; // only serialize the default name
//对变量名称,变量类型,及序列化和非序列华 判断的封装,
BoundField boundField = createBoundField(context, field, name,
TypeToken.get(fieldType), serialize, deserialize);
//然后以函数名为键将BoundField 存起来
BoundField replaced = result.put(name, boundField);
if (previous == null) previous = replaced;
}
if (previous != null) {
throw new IllegalArgumentException(declaredType
+ " declares multiple JSON fields named " + previous.name);
}
}
type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
raw = type.getRawType();
}
return result;
}
getBoundFields返回的数据结构 现在我们回到create 方法 看 return new Adapter<T>(constructor, getBoundFields(gson, type, raw)); 的返回值Adaper<T>类,他继承TypeAdapter 同时保存了 构造器和变量的BoundField 数据集合即变量名称的相关信息,并且重写了读和写 构造函数,
这些操作完成后我们会拿到一个 TypeAdapter<?> 对象,准备工作已经做完了,下面进入真题,开始序列化,过程
TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc)); 拿到adapter
2.((TypeAdapter<Object>) adapter).write(writer, src)
((TypeAdapter<Object>) adapter).write(writer, src); 调用的是Adapte<T> 类的write 开始写,我们进入Adapter<T>类看下write方法实现 ,Adapter<T> 是 ReflectiveTypeAdapterFactory 类的内部静态类。
@Override public void write(JsonWriter out, T value) throws IOException {
//这里 如果 value 也就是我们需要序列化的 为null 将会写入一个空 null
if (value == null) {
out.nullValue();
return;
}
//正式开始序列化的流操作 起始的 “{”
out.beginObject();
try {
for (BoundField boundField : boundFields.values()) {
if (boundField.writeField(value)) {
//保存 函数名
out.name(boundField.name);
//开始拼接写入键和值
boundField.write(out, value);
}
}
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
// 结束序列化流操作 结束 “}”
out.endObject();
}
现在看下boundField 的write 的实现。
ReflectiveTypeAdapterFactory 类 createBoundField 方法内 122 行 不同版本可能有差异。
前边我们说过BoundField 类是组装了变量名 及序列化 和反序列化判断 的封装类,同时还有几个抽象方法,现在我们要看的就是BoundFileld 的实现的地方。
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;
}
具体实现:
return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) {
@SuppressWarnings({"unchecked", "rawtypes"}) // the type adapter and field type always agree
@Override void write(JsonWriter writer, Object value)
throws IOException, IllegalAccessException {
//通过调用write ,通过反射, Field的get 方法获取field 对应函数值 即变量值。
Object fieldValue = field.get(value);
// 实体类 类型 变量 类型 的封装 同时继承自TypeAdapter 重写了方法
TypeAdapter t = jsonAdapterPresent ? typeAdapter
: new TypeAdapterRuntimeTypeWrapper(context, typeAdapter, fieldType.getType());
//开始写
t.write(writer, fieldValue);
}
@Override void read(JsonReader reader, Object value)
throws IOException, IllegalAccessException {
Object fieldValue = typeAdapter.read(reader);
if (fieldValue != null || !isPrimitive) {
field.set(value, fieldValue);
}
}
@Override public boolean writeField(Object value) throws IOException, IllegalAccessException {
if (!serialized) return false;
Object fieldValue = field.get(value);
return fieldValue != value; // avoid recursion for example for Throwable.cause
}
};
现在进入到
TypeAdapterRuntimeTypeWrapper<T> 类的 write 方法中
@Override
public void write(JsonWriter out, T value) throws IOException {
// Order of preference for choosing type adapters
// First preference: a type adapter registered for the runtime type
// Second preference: a type adapter registered for the declared type
// Third preference: reflective type adapter for the runtime type (if it is a sub class of the declared type)
// Fourth preference: reflective type adapter for the declared type
// 实体类 的Type
TypeAdapter chosen = delegate;
/变量值类型的Type
Type runtimeType = getRuntimeTypeIfMoreSpecific(type, value);
// 这里如果变量值不是基本的数据类型 比对成功就会重新负值(这里的理解不是特别到位,有待进一步理解)
if (runtimeType != type) {
TypeAdapter runtimeTypeAdapter = context.getAdapter(TypeToken.get(runtimeType));
if (!(runtimeTypeAdapter instanceof ReflectiveTypeAdapterFactory.Adapter)) {
// The user registered a type adapter for the runtime type, so we will use that
chosen = runtimeTypeAdapter;
} else if (!(delegate instanceof ReflectiveTypeAdapterFactory.Adapter)) {
// The user registered a type adapter for Base class, so we prefer it over the
// reflective type adapter for the runtime type
chosen = delegate;
} else {
// Use the type adapter for runtime type
chosen = runtimeTypeAdapter;
}
}
chosen.write(out, value);
}
假设我们解析到了name 函数 调用到 string 类型适配器的write
public static final TypeAdapter<String> STRING = new TypeAdapter<String>() {
@Override
public String read(JsonReader in) throws IOException {
JsonToken peek = in.peek();
if (peek == JsonToken.NULL) {
in.nextNull();
return null;
}
/* coerce booleans to strings for backwards compatibility */
if (peek == JsonToken.BOOLEAN) {
return Boolean.toString(in.nextBoolean());
}
return in.nextString();
}
@Override
public void write(JsonWriter out, String value) throws IOException {
// 进入jsonWriter 开始流写入
out.value(value);
}
};
进入 jsonWriter 的value 方法 绕了这么大一圈终于到点了。
public JsonWriter value(String value) throws IOException {
if (value == null) {
return nullValue();
}
// 这个方法是拼接 key 的方法,也就是变量名称,同时他还判断了是否在他之前添加“,” 分割符的操作
// 例如 ,“name”
writeDeferredName();
//开始写入value 即变量值之前的操作,确定在key 后面添加“:” 分割符
// 此时拼接 例如 ,“name": 前通过反射获取数组时我们用到了一个有序hashMap ,那么此时name已经是第二个操作的变量了 ,那么写入的字串为 {"age":30,"name":
beforeValue();
//开始写入name 的值
string(value);
//写入完成,重新回到 Adapter<T> 方法的write for 循环中,我们的demo 有三个字段,会走三遍
return this;
}
for (BoundField boundField : boundFields.values()) {//走三遍
if (boundField.writeField(value)) {
//保存 函数名
out.name(boundField.name);
//开始拼接写入键和值
boundField.write(out, value);
}
}
上边说的比较粗糙,那有人就会问了,他是如何保存状态的,因为我们列出的只是一个简单的对像序列化,没有嵌套 数组等,所以我们没有想到这些 ,其他主要有以下几个方法
//获取保存的标示状态 ,用于确定下一步操作
peek();
// 新起一行
newline();
//存储标示
replaceTop(int topOfStack)
最终还是回到开始的地方
public String toJson(Object src, Type typeOfSrc) {
StringWriter writer = new StringWriter();
toJson(src, typeOfSrc, writer);
return writer.toString();
}
通过流将json 字符串返回回来,到此gson 的toJson 过程就结束了。
重新理下详细过程
1.获取一个流对象
2.通过遍历找到实例对象的适配器类型
3.通过反射获取到那个变量名和变量类型的集合
4.遍历集合获取每个变量的值并且找到适配器类型
5.开始通过流写入拼接数据 { "key" : value ,. . . }
阅读过程中如果有理解不到位还请各位读者多加提醒。