通过Gson将Java Array(数组)转换为String的入口是toJson(),那它到底做了什么?
1.Gson的构造函数主要是初始化factories (TypeAdapterFactory 集合),便于在getAapter()根据数据类型返回对应的TypeAdapterFactory,从而获取对应的TypeAdapter进行序列化和反序列化。 toJson()是序列化入口,首先会判断传入的数据是不是空,如为空则调用参数为JsonElement的toJson()方法;若不为空则调用传入Object和Class参数的toJson()方法
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;//html转义
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;
//TypeAdapter的工厂列表
List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
//以下都是往工厂列表加入TypeAdapterFactory
// 构建不能被重载的TypeAdapter
// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);
// 排除器必须在所有的用于自定义的typeAdapter之前
// the excluder must precede all adapters that handle user-defined types
factories.add(excluder);
//用户自定义的typeAdapter工厂
// users' type adapters
factories.addAll(factoriesToBeAdded);
//以下为默认的TypeAdapter
// 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);
//复合的TypeAdapter
// 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(//最后添加反射机制用的factory
constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
this.factories = Collections.unmodifiableList(factories);
}
public String toJson(Object src) {
if (src == null) {
return toJson(JsonNull.INSTANCE);
}
return toJson(src, src.getClass());
}
1.1.1 先看看数据为空的情况。当数据为空时,先调用参数为JsonElement的toJson()。首先会创建一个StringWriter,然后将JsonElement和StringWriter传入到toJson()
public String toJson(JsonElement jsonElement) {
StringWriter writer = new StringWriter();
toJson(jsonElement, writer);
return writer.toString();
}
1.1.2 在方法中创建一个JsonWriter, JsonWriter将StringWriter进行包装,然后将其传入到toJson()中
public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException {
try {
JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
toJson(jsonElement, jsonWriter);
} catch (IOException e) {
throw new JsonIOException(e);
}
}
//默认情况下generateNonExecutableJson和prettyPrinting为false,所以没有做其他操作,只是设置了serializeNulls,默认为false
public JsonWriter newJsonWriter(Writer writer) throws IOException {
if (generateNonExecutableJson) {
writer.write(JSON_NON_EXECUTABLE_PREFIX);
}
JsonWriter jsonWriter = new JsonWriter(writer);
if (prettyPrinting) {
jsonWriter.setIndent(" ");
}
jsonWriter.setSerializeNulls(serializeNulls);
return jsonWriter;
}
1.1.3 获取writer之前的配置信息,然后为其配置信息,之后调用Streams.write(jsonElement, writer)进行写入,最后把之前的配置信息再次配置进去
public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException {
boolean oldLenient = writer.isLenient();
writer.setLenient(true);
boolean oldHtmlSafe = writer.isHtmlSafe();
writer.setHtmlSafe(htmlSafe);
boolean oldSerializeNulls = writer.getSerializeNulls();
writer.setSerializeNulls(serializeNulls);
try {
Streams.write(jsonElement, writer);
} 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.1.4 该方法是Streams类中的方法,它主要调用TypeAdapters中JSON_ELEMENT的writer方法进行写入,JSON_ELEMENT是TypeAdapter类型的
public static void write(JsonElement element, JsonWriter writer) throws IOException {
TypeAdapters.JSON_ELEMENT.write(writer, element);
}
1.1.5 JSON_ELEMENT位于TypeAdapters,它是TypeAdapter的子类,重写了read和writer方法,那么我们重点看writer方法。首先判断数据是否是空类型,若是的话调用writer.nullValue(),直接写入null字符串;若数据是原始数据类型,判断若是number类型,则调用writer.value()将值转换为number进行写入,若是boolean类型,则调用writer.value()将值转换为boolean进行写入,若是原始类型的其他类型,则以String类型进行写入;若value是jsonArray类型的,则以数组的结构进行写入;若value是JsonObject类型的,则以Object的结构进行写入。但是我们设置value是JsonNull类型,所以是直接写入null,这就是当我们传入的数据是null时的执行流程
public static final TypeAdapter<JsonElement> JSON_ELEMENT = new TypeAdapter<JsonElement>() {
@Override public JsonElement read(JsonReader in) throws IOException {
switch (in.peek()) {
case STRING:
return new JsonPrimitive(in.nextString());
case NUMBER:
String number = in.nextString();
return new JsonPrimitive(new LazilyParsedNumber(number));
case BOOLEAN:
return new JsonPrimitive(in.nextBoolean());
case NULL:
in.nextNull();
return JsonNull.INSTANCE;
case BEGIN_ARRAY:
JsonArray array = new JsonArray();
in.beginArray();
while (in.hasNext()) {
array.add(read(in));
}
in.endArray();
return array;
case BEGIN_OBJECT:
JsonObject object = new JsonObject();
in.beginObject();
while (in.hasNext()) {
object.add(in.nextName(), read(in));
}
in.endObject();
return object;
case END_DOCUMENT:
case NAME:
case END_OBJECT:
case END_ARRAY:
default:
throw new IllegalArgumentException();
}
}
@Override public void write(JsonWriter out, JsonElement value) throws IOException {
//若JsonElement为空或者JsonElement的类型为JsonNull,则直接调用writer的nullValue()
if (value == null || value.isJsonNull()) {
out.nullValue();
//若JsonElement的类型是JsonPrimitive,判断JsonPrimitive的数据是number类型,则将数据转换为number进行写入;若JsonPrimitive的数据是boolean类型,则将数据转换为boolean进行写入;JsonPrimitive的数据是其它类型,则将数据转换为String进行写入
} else if (value.isJsonPrimitive()) {
JsonPrimitive primitive = value.getAsJsonPrimitive();
if (primitive.isNumber()) {
out.value(primitive.getAsNumber());
} else if (primitive.isBoolean()) {
out.value(primitive.getAsBoolean());
} else {
out.value(primitive.getAsString());
}
//若JsonElement的类型是JsonArray,则按照数组的结构进行数据写入
} else if (value.isJsonArray()) {
out.beginArray();
for (JsonElement e : value.getAsJsonArray()) {
write(out, e);
}
out.endArray();
//若JsonElement的类型是JsonObject,则按照object的结构进行数据写入
} else if (value.isJsonObject()) {
out.beginObject();
for (Map.Entry<String, JsonElement> e : value.getAsJsonObject().entrySet()) {
out.name(e.getKey());
write(out, e.getValue());
}
out.endObject();
//若不是以上四种结构 则会抛异常
} else {
throw new IllegalArgumentException("Couldn't write " + value.getClass());
}
}
};
1.2.1 第二种情况是若传入的数据不为空。则调用参数为Object和Type类型的toJson()方法。在toJson()中创建一个StringWriter对象,之后调用参数为Object,type,writer的toJson()方法进行数据写入,写入完成之后调用writer.toString()将写入的数据以String的形式返回
public String toJson(Object src, Type typeOfSrc) {
StringWriter writer = new StringWriter();
toJson(src, typeOfSrc, writer);
return writer.toString();
}
1.2.2 在参数为Object,Type,Writer的toJson()方法,创建一个JsonWriter对象,并将Appendable封装到JsonWriter中,之后调用参数为Object,Type,JsonWriter的toJson()方法
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);
}
}
1.2.3 在参数为Object,Type,JsonWriter的toJson()方法中进行数据写入,首先TypeToken通过的get()获取写入的Object的typeToken,然后遍历factories集合,以typeToken为参数调用factory.create(this, type)获取对应的typeAdapter,当获取到对应数据类型的typeAdapter,然后调用typeAdapter.writer()进行写入。对于基本数据类型和数组类型gson已经内置,这里使用数组对应的TypeAdapter,将通过CollectionTypeAdapterFactory进行数据的读写。其中factories是typeAdapterFactory集合,在Gson的构造函数添加了各种内置的数据类型的typeAdapter,以及自定义的typeAdapter。下面我们来看CollectionTypeAdapterFactory是如何进行数据的写入的
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);
}
}
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
//typeTokenCache 是 Gson 中的一个 map 对象,用于储存 TypeAdapter
//typeTokenCache 是一个 Gson 中各个线程公用的一个缓存池
TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
if (cached != null) {
//如果本身就有储存了,就直接返回
return (TypeAdapter<T>) cached;
}
//calls 是一个 ThreadLocal 对象
//ThreadLocal 是 Gson 中单个线程使用的缓存池,在里面存入的对象会在 finally 代码块中清空掉
Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
//判断是否需要清空 ThreadLocal
boolean requiresThreadLocalCleanup = false;
if (threadCalls == null) {
threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
calls.set(threadCalls);
//这里存入了对象,所以需要清空 ThreadLocal
requiresThreadLocalCleanup = true;
}
//如果存在对象,就会在这里取用出来并返回
//FutureTypeAdapter 是一个门面模式的应用,其实本质是使用内部的 TypeAdapter 去处理业务
//如果内部没有存入实际处理业务的 TypeAdapter,就会报错
FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
if (ongoingCall != null) {
return ongoingCall;
}
try {
FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
threadCalls.put(type, call);
//这个方法的主体是这个 for 循环,用于从 Gson 初始化的时候储存的列表中获取到对应的 TypeAdapter
for (TypeAdapterFactory factory : factories) {
//TypeAdapter 的 create(...) 方法对于不是对应类型的参数会返回 null
//Log.i("TypeAdapterFactory","TypeAdapterFactory:"+factory);
TypeAdapter<T> candidate = factory.create(this, type);
if (candidate != null) {
//在此处会存入业务处理的 TypeAdapter
call.setDelegate(candidate);
//在此处存入公用缓存
typeTokenCache.put(type, candidate);
Log.i(TAG,"采用的factory1111:"+factory+"-->"+candidate);
return candidate;
}
}
throw new IllegalArgumentException("GSON (" + GsonBuildConfig.VERSION + ") cannot handle " + type);
} finally {
//清除 ThreadLocal 缓存
threadCalls.remove(type);
if (requiresThreadLocalCleanup) {
calls.remove();
}
}
}
1.2.4 CollectionTypeAdapterFactory实现了TypeAdapterFactory接口,而TypeAdapterFactory我们知道是一个TypeAdapter的创建工厂,所以CollectionTypeAdapterFactory会重写create方法创建一个TypeAdapter进行数据的读写操作
CollectionTypeAdapterFactory的构造函数有1个参数
ConstructorConstructor:是一个专门根据tokenType的泛型类型来构建对应的泛型类型对象,用于在read过程中创建需要的真正的对象
create():通过constructorConstructor.get(type)方法获取ObjectConstructor对象,ObjectConstructor可以在read中创建对应的Collection(集合)对象 ;通过Types.getCollectionElementType(type, rawType)获取集合的元素类型;通过gson.getAdapter(TypeToken.get(elementType))根据集合的元素数据类型返回对应的的TypeAdapter,若元素是String类型的,则会采用TypeAdaptets中对应的String类型的TypeAdapter,若集合中的元素是我们自己定义的Java Object,同时在Json数组中都是由一个个Json Object构成, 所以会使用ObjectTypeAdapter
CollectionTypeAdapterFactory内部构建了一个TypeAdapter专门用来进行序列化和反序列的
Gson:用于返回集合元素应该使用的TypeAdapter
elementType:表明集合中的元素类型
elementTypeAdapter:集合元素的TypeAdapter
ObjectConstructor:用于构建集合对象,在TypeAdapter的read()中被使用
write(JsonWriter out, T value):用于序列化操作(Java Array转Json),在写入之前调用out.beginArray()方法,该方法主要用于写入json字符串的的"["符号,之后遍历客户端传递过来的collection集合,通过elementTypeAdapter.write(out, element)将一个个元素进行写入,集合遍历完成之后了,表示数据写入完成,最后调用out.endArray()写入结束符号"]",那么整个Java Array就被转换为一个标准的json形式的字符串了
read(JsonReader in):用于进行反序列化操作(Json转换为Java Array)。首先会调用constructor.construct()创建Java Array的实例对象,然后调用in.beginArray()设置状态值为EMPTY_ARRAY,JsonReader在读取的时候会根据不同的状态进行不同的操作,然后调用in.hasNext()判断是否有下一个数据,若有的话调用elementTypeAdapter.read(in)根据数据元素对应的TypeAdapter进行read()。当所有的数据都写入完成之后,调用in.endArray()重置状态
ObjectTypeAdapter时Object类型的TypeAdapter,因为Json数组都是由一个个Json对象构建而成,所以在CollectionTypeAdapterFactory在遍历collections,调用 elementTypeAdapter.write(out, element)进行单个元素的写入的时候,就是使用的此TypeAdapter
Gson: 通过构造函数传递进来,用于调用getAdapter()获取元素对应的解析器
write(JsonWriter out, Object value):对传递进来的值进行序列化,但是它不直接参与序列化操作,而是根据传递的参数值的class对象来获取typeAdapter,通过获取的typeAdapter的write(typeAdapter.write(out, value))j进行真正的序列化操作
read(JsonReader in):用于进行反序列化操作。获取当前数据类型,根据不同的数据类型进行读取操作
源码
public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {
private final ConstructorConstructor constructorConstructor;
public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
this.constructorConstructor = constructorConstructor;
}
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
Type type = typeToken.getType();
Class<? super T> rawType = typeToken.getRawType();
if (!Collection.class.isAssignableFrom(rawType)) {
return null;
}
Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType));
ObjectConstructor<T> constructor = constructorConstructor.get(typeToken);
@SuppressWarnings({"unchecked", "rawtypes"}) // create() doesn't define a type parameter
TypeAdapter<T> result = new Adapter(gson, elementType, elementTypeAdapter, constructor);
return result;
}
private static final class Adapter<E> extends TypeAdapter<Collection<E>> {
private final TypeAdapter<E> elementTypeAdapter;
private final ObjectConstructor<? extends Collection<E>> constructor;
public Adapter(Gson context, Type elementType,
TypeAdapter<E> elementTypeAdapter,
ObjectConstructor<? extends Collection<E>> constructor) {
this.elementTypeAdapter =
new TypeAdapterRuntimeTypeWrapper<E>(context, elementTypeAdapter, elementType);
this.constructor = constructor;
}
@Override public Collection<E> read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
Collection<E> collection = constructor.construct();
in.beginArray();
while (in.hasNext()) {
E instance = elementTypeAdapter.read(in);
collection.add(instance);
}
in.endArray();
return collection;
}
@Override public void write(JsonWriter out, Collection<E> collection) throws IOException {
if (collection == null) {
out.nullValue();
return;
}
out.beginArray();
for (E element : collection) {
elementTypeAdapter.write(out, element);
}
out.endArray();
}
}
}
public final class ObjectTypeAdapter extends TypeAdapter<Object> {
//工厂类
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked")
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (type.getRawType() == Object.class) { //该工厂用来创建Object类型的TypeAdapter
return (TypeAdapter<T>) new ObjectTypeAdapter(gson);
}
return null;
}
};
private final Gson gson;
ObjectTypeAdapter(Gson gson) {
this.gson = gson;
}
@Override public Object read(JsonReader in) throws IOException {
JsonToken token = in.peek();//查看元素类型
switch (token) {
case BEGIN_ARRAY:
List<Object> list = new ArrayList<Object>();
in.beginArray();//开始标识
while (in.hasNext()) {//还有下一个元素?
list.add(read(in));
}
in.endArray();//结束标识
return list;
case BEGIN_OBJECT://对象
Map<String, Object> map = new LinkedTreeMap<String, Object>();
in.beginObject();
while (in.hasNext()) {
map.put(in.nextName(), read(in));
}
in.endObject();
return map;
case STRING:
return in.nextString();
case NUMBER:
return in.nextDouble();
case BOOLEAN:
return in.nextBoolean();
case NULL:
in.nextNull();
return null;
default:
throw new IllegalStateException();
}
}
@SuppressWarnings("unchecked")
@Override public void write(JsonWriter out, Object value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
//gson.getAdapter获取对应类型的TypeAdapter
TypeAdapter<Object> typeAdapter = (TypeAdapter<Object>) gson.getAdapter(value.getClass());
if (typeAdapter instanceof ObjectTypeAdapter) {
out.beginObject();
out.endObject();
return;
}
typeAdapter.write(out, value);
}
}
1.2.5 从上面我们看到在序列化过程中,首先会根据客户端传递过来的Java Array的真实类型来获取对应的TypeAdapterFactory,TypeAdapterFactory会有一个对应的typeAdapter,调用这个typeAdapter的write()方法就可实现序列化操作,而在write方法中会循环遍历Collection集合,每一个元素都会有对应的typeAdapter,调用元素的typeAdapter的write方法进行元素的序列化操作,那么每一个元素就会进行具体元素的序列化操做,以此来完成整个数组的序列化操作
1.2.6 在Gson的序列化操作过程中最终是通过JsonWriter将Java Array转换为一个Json的字符串形式,JsonWriter中含有各种进行序列化的操作
public class JsonWriter implements Closeable, Flushable {
private static final String[] REPLACEMENT_CHARS;
private static final String[] HTML_SAFE_REPLACEMENT_CHARS;
static {
REPLACEMENT_CHARS = new String[128];
for (int i = 0; i <= 0x1f; i++) {
REPLACEMENT_CHARS[i] = String.format("\\u%04x", (int) i);
}
REPLACEMENT_CHARS['"'] = "\\\"";
REPLACEMENT_CHARS['\\'] = "\\\\";
REPLACEMENT_CHARS['\t'] = "\\t";
REPLACEMENT_CHARS['\b'] = "\\b";
REPLACEMENT_CHARS['\n'] = "\\n";
REPLACEMENT_CHARS['\r'] = "\\r";
REPLACEMENT_CHARS['\f'] = "\\f";
HTML_SAFE_REPLACEMENT_CHARS = REPLACEMENT_CHARS.clone();
HTML_SAFE_REPLACEMENT_CHARS['<'] = "\\u003c";
HTML_SAFE_REPLACEMENT_CHARS['>'] = "\\u003e";
HTML_SAFE_REPLACEMENT_CHARS['&'] = "\\u0026";
HTML_SAFE_REPLACEMENT_CHARS['='] = "\\u003d";
HTML_SAFE_REPLACEMENT_CHARS['\''] = "\\u0027";
}
/** The output data, containing at most one top-level array or object. */
private final Writer out;
private int[] stack = new int[32];
private int stackSize = 0;
{
//在数组的第一位写入EMPTY_DOCUMENT 并将stackSize变为1
push(EMPTY_DOCUMENT);
}
/**
* 一个字符串 在默认中是null 在格式化打印中是空格 主要是在格式话字符串后
*/
private String indent=" ";
/**
* The name/value separator; either ":" or ": ".
*/
private String separator = ":";
private boolean lenient;
private boolean htmlSafe;
private String deferredName;
private boolean serializeNulls = true;
public JsonWriter nullValue() throws IOException {
if (deferredName != null) {
//若属性名不为空 而且可以序列化空数据值属性 则写入属性名
if (serializeNulls) {
writeDeferredName();
} else {
deferredName = null;
return this; // skip the name and the value
}
}
//根据对应的状态 进行一些操作 包含修改状态 换行 写入逗号或分号等
beforeValue();
//写入null
out.write("null");
return this;
}
public JsonWriter beginObject() throws IOException {
//这个方法主要的作用是在不同的 object 之间加逗号
//如果是起始第一个 object 就不需要了,会直接跳过
writeDeferredName();
JsonWriter jsonWriter=open(EMPTY_OBJECT, '{');
return jsonWriter;
}
public JsonWriter beginArray() throws IOException {
writeDeferredName();
return open(EMPTY_ARRAY, '[');
}
public JsonWriter endArray() throws IOException {
return close(EMPTY_ARRAY, NONEMPTY_ARRAY, ']');
}
public JsonWriter endObject() throws IOException {
JsonWriter jsonWriter=close(EMPTY_OBJECT, NONEMPTY_OBJECT, '}');
return jsonWriter;
}
private JsonWriter open(int empty, char openBracket) throws IOException {
//该方法会使用 stack 中最新的指令进行操作
//根据getPeek()获取stacksize对应的值 然后根据其当前状态标识下一个状态是什么
beforeValue();
//push(...) 方法会检查 stack 数组的容积,适时进行扩容,并把传入的指令存放到数组中
push(empty);
//写入字符串
out.write(openBracket);
return this;
}
private void beforeValue() throws IOException {
//peek() 方法会根据 stack 数组的指令获取到下一个要操作的字符类型
//会从stack数组中根据static 索引位置值 取对应的值
switch (peek()) {
case NONEMPTY_DOCUMENT://7 表示文档是一个数组或对象
if (!lenient) {
throw new IllegalStateException(
"JSON must have only one top-level value.");
}
case EMPTY_DOCUMENT://6 未启动任何对象或数组
//replaceTop(...) 方法会将 stack 最新的指令更新成传入的参数
//在begin
replaceTop(NONEMPTY_DOCUMENT);
break;
case EMPTY_ARRAY://1 若数组是空 不需要加逗号
replaceTop(NONEMPTY_ARRAY);
//换行
newline();
break;
case NONEMPTY_ARRAY://2 若数组有一个元素以上 需要在下一个元素之前加逗号和换行符
out.append(',');
newline();
break;
case DANGLING_NAME://4 当对象key 写入之后 需要加入分号 后面就是value值
//separator 即为 ":" (冒号)
out.append(separator);
replaceTop(NONEMPTY_OBJECT);
break;
default:
throw new IllegalStateException("Nesting problem.");
}
}
private void beforeName() throws IOException {
int context = peek();
if (context == NONEMPTY_OBJECT) { // first in object
Log.i("beginObject","beforeName 写入逗号:"+out.toString());
out.write(',');
} else if (context != EMPTY_OBJECT) { // not in an object!
throw new IllegalStateException("Nesting problem.");
}
//1.第一次写入属性名 通过peek()得到状态值为EMPTY_OBJECT 而且indent为空 所以newline()没做任何操作
//之后将stackSize-1位置的状态设置为DANGLING_NAME
//2.第二次写入的时候 通过peek()的到状态值为NONEMPTY_OBJECT 此时写入逗号,之后和第一次一样newline()没做任何操作
//再次将之后将stackSize-1位置的状态设置为DANGLING_NAME
//如此重复
//
newline();
replaceTop(DANGLING_NAME);
}
private int peek() {
if (stackSize == 0) {
throw new IllegalStateException("JsonWriter is closed.");
}
return stack[stackSize - 1];
}
private void replaceTop(int topOfStack) {
stack[stackSize - 1] = topOfStack;
}
private void newline() throws IOException {
//indent一般为空格
if (indent == null) {
return;
}
//换行
out.write('\n');
for (int i = 1, size = stackSize; i < size; i++) {
out.write(indent);
}
}
private void push(int newTop) {
if (stackSize == stack.length) {
stack = Arrays.copyOf(stack, stackSize * 2);
}
stack[stackSize++] = newTop;
}
private void writeDeferredName() throws IOException {
if (deferredName != null) {
//写入value 第一次的话 没有任何操作 只是修改状态为DANGLING_NAME
beforeName();
//将deferredName 变成"deferredName"写入
string(deferredName);
//写入之后 deferredName设置为null
deferredName = null;
}
}
private void string(String value) throws IOException {
String[] replacements = htmlSafe ? HTML_SAFE_REPLACEMENT_CHARS : REPLACEMENT_CHARS;
out.write('\"');
int last = 0;
int length = value.length();
for (int i = 0; i < length; i++) {
char c = value.charAt(i);
String replacement;
if (c < 128) {
replacement = replacements[c];
if (replacement == null) {
continue;
}
} else if (c == '\u2028') {
replacement = "\\u2028";
} else if (c == '\u2029') {
replacement = "\\u2029";
} else {
continue;
}
if (last < i) {
out.write(value, last, i - last);
}
out.write(replacement);
last = i + 1;
}
if (last < length) {
out.write(value, last, length - last);
}
out.write('\"');
}
private JsonWriter close(int empty, int nonempty, char closeBracket)
throws IOException {
int context = peek();//NONEMPTY_OBJECT
if (context != nonempty && context != empty) {
throw new IllegalStateException("Nesting problem.");
}
//deferredName 不为空 表示没有写入 抛异常
if (deferredName != null) {
throw new IllegalStateException("Dangling name: " + deferredName);
}
stackSize--;
if (context == nonempty) {
newline();
}
out.write(closeBracket);
return this;
}
}
- 方法说明
nullValue():若此时序列化的对象是空,或者Json中key对应的value值是null,则调用该方法,它会判断deferredName(Java Object的的属性名)是否为空,若不为空则则写入属性名;然后通过beforeValue()判断是否需要写入key/value之间的分号“:”,最后通过out.write("null")写入null
beginObject():在序列化Object类型的数据之前需要首先先调用该方法,它主要用于写入开始符号“(”,并将状态值从EMPTY_DOCUMENT变成EMPTY_OBJECT
beginArray():在序列化Array类型的数据之前需要首先先调用该方法,它主要用于写入开始符号"[",并将状态值从EMPTY_DOCUMENT变成EMPTY_ARRAY
endObject():在序列化Object类型的数据完成之后调用该方法,它主要用于写入结束符号"}"
endArray():在序列化Array类型的数据完成之后调用该方法,它主要用于写入结束符号"]"
peek():获取stackSize-1位置的状态值,也就是当前状态值
newline():写入换行符
push():修改当前状态,并将stackSize加1
name():将Java Object的属性名赋值给deferredName
string():将属性名/属性值添加双引号写入
writeDeferredName():在value方法中被调用,主要写入属性名(deferredName),会判断属性名是否为空,若不为空则先调用beforeName()判断在name的前面 是否需要添加逗号“,” ,因为第一次会调用beginObject()/beginArray()方法时将状态变成EMPTY_OBJECT/EMPTY_ARRAY,此时不会写入逗号(","),但是在写入下一个key/value值时状态变成NONEMPTY_OBJECT/NONEMPTY_ARRAY将会写入逗号(","),逗号写入完成之后调用string()将属性名写入进去,写入完成之后调用replaceTop()将状态变成DANGLING_NAME
beforeValue():写入value之前做的一些操作。该方法会根据对应的状态 进行一些操作 包含修改状态 换行 写入逗号或分号等
value():写入key/value值,通过writeDeferredName()判断是否需要写入逗号(","),之后通过string()写入属性名的值;通过beforeValue()修改状态值,并根据状态是否需要写入逗号,分号等,最后通过string()写入属性对应的vlaue值
close():写入结束符号
open(): 写入结束符号
总结一下:通过Gson的toJson()进行序列化操作,那么具体流程是怎么样的?到底是怎样一步步写入数据,将Java Array转换为Json字符串的
1.当创建Gson()对象时,在Gson的构造函数中初始化一个TypeAdapterFactory的集合,它包含了各种数据类型的解析器,若开发者自己定义了解析器,也会被添加到集合中,以便于序列化时调用getAdapter()获取对应类型的TypeAdapter
2.调用gson.toJson(object)方法,将数据传递进来,开始进行序列化操作
3.在toJson()方法中判断传入的数据是否为空
若传入的数据为空
1.调用Streams.write(jsonElement, writer)方法进行写入,jsonElement为JsonNull; writer为JsonWriter
2.然后在Streams.write()方法中调用 TypeAdapters.JSON_ELEMENT.write()进行写入,JSON_ELEMENT是一个TypeAdapter,用于对JsonElement类型的数据进行写入
3.在JSON_ELEMENT中因为传入的数据是JsonNull,在TypeAdapter的write会调用nullValue(),最终通过Writer写入“null”字符串
若传入的数据不为空
1.则通过TypeToken.get(typeOfSrc),创建一个TypeToken对象,这个TypeToken可以获取Java Object的类型
2.之后以此为参数,遍历factories,创建可以解析Java Object对应数据的的TypeAdapter,若创建成功,就表示成功找到了对应的typeAdapter。对于不同数据类型有不同的typeAdapter解析器,Gson已经有了一些内置的typeAdapter(可以在TypeAdapters查看),同时也可以客户端自己定义对应类型的typeAdapter,在构建Gson的时候这些解析器会被添加到factories中,若定义的Java Object是自定义类型,也没有添加特定的typeAdapter,那么则采用通用的ReflectiveTypeAdapterFactory以反射的形式进行数据的处理
3.找到对应的TypeAdapter后调用typeAdapter.write()方法,那么一般对于Java Array,若没有采用TypeAdapter注解注册对应的typeAdapter,那么就会使用CollectionTypeAdapterFactory进行处理,所以我们看看CollectionTypeAdapterFactory
4.CollectionTypeAdapterFactory的构造函数中包含ConstructorConstructor(用于构建Java Object的实例对象)
5.CollectionTypeAdapterFactory实现了TypeAdapterFactory接口,重写了create(),在该方法中通过gson.getAdapter(TypeToken.get(elementType))获取元素的TypeAdapter,在TypeAdapter的write/read中被使用,针对集合中具体的元素类型采用对应的TypeAdapter进行序列化和反序列化
6.在CollectionTypeAdapterFactory的typeAdapter的write方法中,首先会调用out.beginArray()写入json字符串的开始符号“[”,此时JsonWriter的stack状态数组中第一个位置的状态值由EMPTY_DOCUMENT变成NONEMPTY_DOCUMENT,第二个位置的状态值变成EMPTY_ARRAY
7.然后遍历collection集合, 调用elementTypeAdapter.write(out, element)写入元素数据,若集合中是自定义的Java Object,那么elementTypeAdapter是ObjectTypeAdapter类型,也就是Object类型的,那么就会调用ObjectTypeAdapter的write方法,在ObjectTypeAdapter的write方法会根据gson.getAdapter(value.getClass())获取元素对应的typeAdapter,因为元素没有使用JsonAdapter注解添加自定义的TypeAdapter,所以当做一个Java Object,那么采用ReflectiveTypeAdapterFactory进行元素的json字符串的写入,在写入过程中,第一个元素的typeAdapter调用JsonWriter,beginObject(),因为此时的状态为EMPTY_ARRAY,不会在写入整个元素的数据之前写入逗号,但是当第二元素及后面的元素的typeAdapter调用JsonWriter,beginObject()时状态为NONEMPTY_OBJECT,会在写入整个元素的数据之前写入逗号,那么这样就将整个数组的元素都写入进去了,且每一个元素之间会有一个逗号
8.遍历集合元素写入完成之后,调用endArray()写入json字符串的结束符号“]”,整个json数组字符串被写入完成