Gson源码解析之-fromJson

上面我们学习了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;
  }

前面是一些准备的fromJson 构造函数,下面看主要部分

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

   

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章