追踪解析Gson源码(2)

接上篇

三 JsonReader 和 JsonWriter

在进行 json 的序列化和反序列化源码解析之前先了解一下其主体工具类。

1 JsonReader

JsonReader 是 Gson 中用于 json 反序列化的主体。

在 Gson 包中可以不使用 Gson 门面而单独使用 JsonReader 进行 json 的反序列化:

public static void main(String[] args){
    //json 字符串
    String json = "{\"name\":\"zhangsan\",\"age\":18}";
    //使用 StringReader 包装字符串
    StringReader strReader = new StringReader(json);
    //使用 JsonReader 包装 StringReader
    JsonReader jsonReader = new JsonReader(strReader);
    //创建一个参数均为空的目标对象
    Person p = new Person();
    try {
        //beginObject(...) 方法用于告诉 jsonReader 开始读取一个 object
        jsonReader.beginObject();
        //while 循环读取
        while(jsonReader.hasNext()){
            //读取一个 json 的 key 值
            String name = jsonReader.nextName();
            switch (name){
                case "name": 
                    p.setName(jsonReader.nextString()); //读取一个 String 作为 value,存入对象中
                    break;
                case "age": 
                    p.setAge(jsonReader.nextInt()); //读取一个 int 作为 value,存入对象中
                    break;
            }
        }
        jsonReader.endObject();
    } catch (IOException e) {
        e.printStackTrace();
    }
    System.out.println("名字:" + p.getName());
    System.out.println("年龄:"  +p.getAge())
}

JsonReader 的构造方法:

//JsonReader.class
public JsonReader(Reader in) {
    if (in == null) {
        throw new NullPointerException("in == null");
    }
    //传入的 Reader 中保存着要读取的 json 主体 
    //此处比较常用的是 StringReader,但是也可以是 FileReader 等其它 Reader 接口的实现类
    this.in = in;
}

JsonReader 仅此一个构造方法,创建对象均调用此方法。

先来看一下 JsonReader 中非常重要的一个非公开方法 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
}

方法虽然比较长,但是代码其实比较简单,本质上是根据 stack 指令去修改 peeked 的值,从而达到状态控制的效果。

再来看 beginObject() 方法:

//JsonReader.class
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() 方法:

//JsonReader.class
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;
}

nextQuotedValue(...) 方法里实际上是比较繁琐的字符串处理,在这里暂时不展开了。

hasNext() 和 nextString() 方法其实都和 nextName() 方法差不多,本质上都是根据 peeked 的值去进入不同的 if 语句来处理字符串。

2 JsonWriter

JsonWriter 是 Gson 中用于 json 序列化的主体。

和 JsonReader 一样,也可以不使用 Gson 门面而单独使用 JsonWriter 进行 json 的序列化:

public static void main(String[] args){
    //组装 bean
    Person person = new Person();
    person.setName("zhangsan");
    person.setAge(18);

    //创建一个 StringWriter,本质是 StringBuffer 的封装
    StringWriter writer = new StringWriter();
    //用 JsonWriter 去封装 StringWriter
    JsonWriter jsonWriter = new JsonWriter(writer);
    try {
        //启动一个 object 的写入
        jsonWriter.beginObject();
        //写入 key-value
        jsonWriter.name("name").value(person.getName());
        jsonWriter.name("age").value(person.getAge());
        //结束命令
        jsonWriter.endObject();
        //将 JsonWriter 里的数据存入到 StringWriter 中
        jsonWriter.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }

    System.out.println(writer.toString());
}

JsonWriter 的构造方法:

//JsonWriter.class
public JsonWriter(Writer out) {
    if (out == null) {
        throw new NullPointerException("out == null");
    }
    this.out = out;
}

追踪一下 beginObject() 方法:

//JsonWriter.class
public JsonWriter beginObject() throws IOException {
    //这个方法主要的作用是在不同的 object 之间加逗号
    //如果是起始第一个 object 就不需要了,会直接跳过
    writeDeferredName();
    return open(EMPTY_OBJECT, "{");
}

继续追踪 open(...) 方法:

//JsonWriter.class
private JsonWriter open(int empty, String openBracket) throws IOException {
    //该方法会使用 stack 中最新的指令进行操作
    beforeValue();
    //push(...) 方法会检查 stack 数组的容积,适时进行扩容,并把传入的指令存放到数组中
    push(empty);
    //写入字符串
    out.write(openBracket);
    return this;
}

JsonWriter 中没有 JsonReader 中那么复杂的指令操作,所以没有引入 peeked 变量,仅仅使用 stack 数组来控制状态。

stack 的控制封装在 beforeValue() 方法中:

//JsonWriter.class
private void beforeValue() throws IOException {
    //peek() 方法会根据 stack 数组的指令获取到下一个要操作的字符类型
    switch (peek()) {
        case NONEMPTY_DOCUMENT:
            if (!lenient) {
            throw new IllegalStateException(
                "JSON must have only one top-level value.");
            }
        case EMPTY_DOCUMENT:
            //replaceTop(...) 方法会将 stack 最新的指令更新成传入的参数
            replaceTop(NONEMPTY_DOCUMENT);
            break;

        case EMPTY_ARRAY:
            replaceTop(NONEMPTY_ARRAY);
            //换行
            newline();
            break;
        case NONEMPTY_ARRAY:
            out.append(',');
            newline();
            break;
        case DANGLING_NAME:
            //separator 即为 ":" (冒号)
            out.append(separator);
            replaceTop(NONEMPTY_OBJECT);
            break;
        default:
            throw new IllegalStateException("Nesting problem.");
        }
}

来看一下 name(...) 方法:

//JsonWriter.class
public JsonWriter name(String name) throws IOException {
    if (name == null) {
      throw new NullPointerException("name == null");
    }
    if (deferredName != null) {
      throw new IllegalStateException();
    }
    if (stackSize == 0) {
      throw new IllegalStateException("JsonWriter is closed.");
    }
    //这一行代码中会暂时将传入的 name 参数保存在一个全局变量中,
    //所以 JsonWriter 在调用 value(...) 方法之前不能再调用 name(...) 方法了,不然在上方的判断中会报错
    deferredName = name;
    return this;
}

来看一下 value(...) 方法:

//JsonWriter.class
public JsonWriter value(String value) throws IOException {

    if (value == null) {
        //nullValue() 方法会在 value 值的地方存入一个 null
          return nullValue();
    }
    //这一方法会将 之前保存在 deferredName 中的字符串写入到 writer 中
    //方法中会处理加逗号、将 deferredName 变量清空等问题
    //核心是调用 string(...) 方法写入
    writeDeferredName();
    //更新 stack 指令
    beforeValue();
    //和上方写入 deferredName 一样,此处调用写入 value
    string(value);
    return this;
  }

总的来说 JsonWriter 比 JsonReader 简单,简要描述一下不过多展开。

四 JSON 字符串转 Bean

该 part 的起点:

Person person = gson.fromJson(json,Person.class);

追踪 fromJson(...) 方法:

//Gson.class
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
    //将字符串转成 object 的主体方法
    //3.1
    Object object = fromJson(json, (Type) classOfT);

    return Primitives.wrap(classOfT).cast(object);
}

先来看一下上述的第二行代码:

return Primitives.wrap(classOfT).cast(object);

Primitives.wrap(...) 方法的实现:

//Primitives.class
public static <T> Class<T> wrap(Class<T> type) {
    //PRIMITIVE_TO_WRAPPER_TYPE 是一个 map 对象
    //$Gson$Preconditions.checkNotNull(...) 用来效验 type 不为空
    @SuppressWarnings("unchecked")
    Class<T> wrapped = (Class<T>) PRIMITIVE_TO_WRAPPER_TYPE.get(
        $Gson$Preconditions.checkNotNull(type));
    //如果 map 中不存在 type 为 key 的值,则返回 type,否则返回取到的 value
    return (wrapped == null) ? type : wrapped;
}

PRIMITIVE_TO_WRAPPER_TYPE 是一个定义在 Primitives 中的 map 对象:

//Primitives.class
private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER_TYPE;

PRIMITIVE_TO_WRAPPER_TYPE 中主要存放了 float、int、double 等原始类型的 class:

//Primitives.class
static {
    Map<Class<?>, Class<?>> primToWrap = new HashMap<Class<?>, Class<?>>(16);
    Map<Class<?>, Class<?>> wrapToPrim = new HashMap<Class<?>, Class<?>>(16);

    //以下代码是将原始类型和包装类型存入两个 map 的过程
    add(primToWrap, wrapToPrim, boolean.class, Boolean.class);
    add(primToWrap, wrapToPrim, byte.class, Byte.class);
    add(primToWrap, wrapToPrim, char.class, Character.class);
    add(primToWrap, wrapToPrim, double.class, Double.class);
    add(primToWrap, wrapToPrim, float.class, Float.class);
    add(primToWrap, wrapToPrim, int.class, Integer.class);
    add(primToWrap, wrapToPrim, long.class, Long.class);
    add(primToWrap, wrapToPrim, short.class, Short.class);
    add(primToWrap, wrapToPrim, void.class, Void.class);

    //Collections.unmodifiableMap(...) 返回一个只能阅读不能修改的 map
    //原始类型作为 key,包装类型作为 value
    PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap);
    //包装类型作为 value,原始类型作为 key
    WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim);
}

由此可见 Primitives.wrap(...) 本质上是判断传入的 type 是否是原始类型,如果是,则会转换成包装类型并返回。

至于 Primitives.wrap(classOfT).cast(object) 中的 cast(...),则是定义在 Class 中的方法:

//Class.class
@HotSpotIntrinsicCandidate
public T cast(Object obj) {
    //isInstance(...) 方法等价于关键词 instanceof
    //如果 obj 不为 null 且 不为该 Class 对象的子类,则会抛出错误
    if (obj != null && !isInstance(obj))
        throw new ClassCastException(cannotCastMsg(obj));
    return (T) obj;
}

代码比较简单,本质上就是强转类型。

再来看这行代码:

Object object = fromJson(json, (Type) classOfT);

追踪具体实现:

//Gson.class
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
    //非 null 判断
    if (json == null) {
      return null;
    }
    //StringReader 是一个 jdk 中存在的 String 和 Reader 的关联封装类
    StringReader reader = new StringReader(json);
    //主体功能实现方法
    T target = (T) fromJson(reader, typeOfT);
    //返回一个指定泛型的对象
    return target;
}

继续追踪重载方法:

//Gson.class
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
    //初始化一个 JsonReader
    JsonReader jsonReader = newJsonReader(json);
    //主体功能实现方法
    T object = (T) fromJson(jsonReader, typeOfT);
    //在整个反序列化过程结束之前效验 jsonReader 的 peeked 的状态
    //如果 peeker 未处于结束状态,则会报错
    assertFullConsumption(object, jsonReader);
    return object;
}

继续追踪重载方法:

//Gson.class
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
    boolean isEmpty = true;
    boolean oldLenient = reader.isLenient();
    //打开 reader 的标准化检验
    reader.setLenient(true);
    try {
        //此处相当于调用了一次 JsonReader 中的 doPeek() 方法
        reader.peek();
        isEmpty = false;
        //TypeToken 本质上是 Class 的增强封装类
        TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
        //根据 TypeToken 获取对应的能够处理其类型的 TypeAdapter
        TypeAdapter<T> typeAdapter = getAdapter(typeToken);
        //反射创建 object
        T object = typeAdapter.read(reader);
        return object;
    } catch (EOFException e) {
        if (isEmpty) {
            return null;
        }
        throw new JsonSyntaxException(e);
    } catch (IllegalStateException e) {
          throw new JsonSyntaxException(e);
    } catch (IOException e) {
        throw new JsonSyntaxException(e);
    } catch (AssertionError e) {
          throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e);
    } finally {
          reader.setLenient(oldLenient);
    }
}

先来看一下 getAdapter(...) 方法:

//Gson.class
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
            TypeAdapter<T> candidate = factory.create(this, type);
            if (candidate != null) {
                //在此处会存入业务处理的 TypeAdapter
                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();
        }
    }
}

到此为止 json 的反序列化就基本完毕了.

五 Bean 转 JSON 字符串

该 part 的起点:

String json2 = gson.toJson(person);

追踪 toJson(...) 方法:

//Gson.class
public String toJson(Object src) {
    if (src == null) {
      return toJson(JsonNull.INSTANCE);
    }
    return toJson(src, src.getClass());
}

toJson(JsonNull.INSTANCE) 方法最后会输出一个 null 字符串,不多展开了。

继续来关注下方主要实现逻辑:

//Gson.class
public String toJson(Object src, Type typeOfSrc) {
    //新建一个 StringWriter
    StringWriter writer = new StringWriter();
    //主要逻辑
    toJson(src, typeOfSrc, writer);
    //返回
    return writer.toString();
}

继续追踪主要逻辑方法:

//Gson.class
public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {
    try {
        //这里将 StringWriter 包装成了 JsonWriter
        JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
        //主要逻辑
        toJson(src, typeOfSrc, jsonWriter);
    } catch (IOException e) {
          throw new JsonIOException(e);
    }
}

继续追踪主要逻辑方法:

//Gson.class
public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
    //获取适配的 TypeAdapter
    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) {
          throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e);
    } finally {
        //还原
          writer.setLenient(oldLenient);
          writer.setHtmlSafe(oldHtmlSafe);
          writer.setSerializeNulls(oldSerializeNulls);
    }
}

基本的逻辑都在上面讲过了,不赘述。

到此为止 json 的序列化就基本完毕了。

四 总结

Gson 的代码封装很薄,本身不难,但是为了照顾兼容性,代码中存在很多条件判断,导致代码看上去很繁琐。同时为了兼顾性能做了很多有意思的设计,比如获取适配器的时候的双缓存设计,应该是为了提高解析器的复用效率,具体有待研究。


总结一下 Gson 的基本思路:

· 解析器(Gson)将使用者传入的字符串或对象存入读取器(Reader)或者写入器(Writer)中

· 解析器遍历并获取能够处理对应类型的适配器工厂(TypeAdapterFactory)

· 适配器工厂会创建出对应类型的适配器(TypeAdapter)

· 解析器将阅读器或写入器交给适配器

· 适配器自行通过业务逻辑操作读取器或写入器,输出需要的结果

· 解析器接收此输出,并交给使用者

五 一点唠叨

· Gson 太过强调功能的全面,解析器的初始化非常复杂

· JsonReader 的状态控制太过复杂和精密,笔者到现在也没全部弄清楚

· 在本篇源码解析中,Gson 内部还有一些拓展功能,比如 JsonElement、JsonParser 等的工具类没有提及

· 仅为个人的学习笔记,可能存在错误或者表述不清的地方,有缘补充

相关推荐