Gson全解析之二:JsonReader的其它方法

Posted 王梵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Gson全解析之二:JsonReader的其它方法相关的知识,希望对你有一定的参考价值。

上篇文章的示例代码

String json = "\\"name\\":\\"王成wisely\\",\\"age\\":\\"24\\"";
private void readJson2User()
    User user = new User();
    StringReader reader = new StringReader(json);
    JsonReader jsonReader = new JsonReader(reader);
    try 
        jsonReader.beginObject();
        while (jsonReader.hasNext())
            String name = jsonReader.nextName();
            switch (name)
                case "name":
                    user.name = jsonReader.nextString();
                    break;
                case "age":
                    user.age = jsonReader.nextInt();
                    break;
            

        
        jsonReader.endObject();
     catch (IOException e) 
        e.printStackTrace();
    

我们已经说完了beginObject()方法的源码,下面接着按示例代码的调用顺序来分析一下JsonReader的其它方法。

hasNext()


public boolean hasNext() throws IOException 
  int p = peeked;
  if (p == PEEKED_NONE) 
    p = doPeek();
  
  return p != PEEKED_END_OBJECT && p != PEEKED_END_ARRAY;

在上一篇的最后,peeked被赋值为PEEKED_NONE,程序进入到doPeek()方法。

private int doPeek() throws IOException 
    int peekStack = stack[stackSize - 1];
    if (peekStack == JsonScope.EMPTY_ARRAY) 
      stack[stackSize - 1] = JsonScope.NONEMPTY_ARRAY;
     else if (peekStack == JsonScope.NONEMPTY_ARRAY) 
      ...
     else if (peekStack == JsonScope.EMPTY_OBJECT || peekStack == JsonScope.NONEMPTY_OBJECT) 
      stack[stackSize - 1] = JsonScope.DANGLING_NAME;
      // Look for a comma before the next element.
      if (peekStack == JsonScope.NONEMPTY_OBJECT) 
        ...
      
      int c = nextNonWhitespace(true);
      switch (c) 
      case '"':
        return peeked = PEEKED_DOUBLE_QUOTED_NAME;
      case '\\'':
        ...
      case '':
        ...
      default:
        ...
      
     else if (peekStack == JsonScope.DANGLING_NAME) 
      ...
     else if (peekStack == JsonScope.EMPTY_DOCUMENT) 
      ...
     else if (peekStack == JsonScope.NONEMPTY_DOCUMENT) 
      ...
     else if (peekStack == JsonScope.CLOSED) 
      ...
    

    int c = nextNonWhitespace(true);
    switch (c) 
    case ']':
      ...
    case ';':
    case ',':
      ...
    case '\\'':
      ...
    case '"':
      ...
    case '[':
      return peeked = PEEKED_BEGIN_ARRAY;
    case '':
      return peeked = PEEKED_BEGIN_OBJECT;
    default:
      pos--; // Don't consume the first character in a literal value.
    
    ...
    return peeked = PEEKED_UNQUOTED;
  

第2行,stackSize=2,peekStack=stack[1]=JsonScope.EMPTY_OBJECT。
第8行,stack[1]=JsonScope.DANGLING_NAME;

stack数组value
stack[0]JsonScope.EMPTY_DOCUMENT JsonScope.NONEMPTY_DOCUMENT
stack[1]JsonScope.EMPTY_OBJECT
stack[1]JsonScope.DANGLING_NAME

第13行

int c = nextNonWhitespace(true);
private int nextNonWhitespace(boolean throwOnEof) throws IOException 
    char[] buffer = this.buffer;
    int p = pos;
    int l = limit;
    while (true) 
      if (p == l) 
        ...
      

      int c = buffer[p++];
      if (c == '\\n') 
        lineNumber++;
        lineStart = p;
        continue;
       else if (c == ' ' || c == '\\r' || c == '\\t') 
        continue;
      

      if (c == '/') 
        ...
       else if (c == '#') 
        ...
       else 
        pos = p;
        return c;
      
    
    ...
  

直接看第10行

int c = buffer[p++];

int c = buffer[1]=34,在ANSCII码中34就是双引号,p=2。

01

第24行,pos=p=2,将c作为返回值返回到doPeek()方法中。
doPeek()中运行到第16行

peeked = PEEKED_DOUBLE_QUOTED_NAME;
peeked的值
PEEKED_NONE
PEEKED_BEGIN_OBJECT
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME

程序回到hasNext()方法中

return p != PEEKED_END_OBJECT && p != PEEKED_END_ARRAY

由于p=PEEKED_DOUBLE_QUOTED_NAME,所以hasNext()方法返回true。

nextName()


public String nextName() throws IOException 
    int p = peeked;
    if (p == PEEKED_NONE) 
      p = doPeek();
    
    String result;
    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()
          + " at line " + getLineNumber() + " column " + getColumnNumber());
    
    peeked = PEEKED_NONE;
    return result;
  

根据hasNext()方法可知,p=PEEKED_DOUBLE_QUOTED_NAME,程序运行到第12行,

nextQuotedValue('"');
private String nextQuotedValue(char quote) throws IOException 
    // Like nextNonWhitespace, this uses locals 'p' and 'l' to save inner-loop field access.
    char[] buffer = this.buffer;
    StringBuilder builder = new StringBuilder();
    while (true) 
      int p = pos;
      int l = limit;
      /* the index of the first character not yet appended to the builder. */
      int start = p;
      while (p < l) 
        int c = buffer[p++];

        if (c == quote) 
          pos = p;
          builder.append(buffer, start, p - start - 1);
          return builder.toString();
         else if (c == '\\\\') 
          ...
         else if (c == '\\n') 
          ...
        
      
      ...
    
  

第9行,start=p=2,之后进入while循环

int c = buffer[p++];

当p=6时,c=buffer[6]=34,也就是双引号,同时,p增加1,p=7

builder.append(buffer, start, p - start - 1);

上面是第15行,p-start-1=7-2-1=4。

01234567
name

获取到的字符串就是2-6之间的字符拼接而成,也就是name。将name作为返回值返回到nextName()中,程序运行到第17行

peeked = PEEKED_NONE;
peeked的值
PEEKED_NONE
PEEKED_BEGIN_OBJECT
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE

最终,nextName()将字符串name作为返回值返回。

nextString()


public String nextString() throws IOException 
    int p = peeked;
    if (p == PEEKED_NONE) 
      p = doPeek();
    
    String result;
    if (p == PEEKED_UNQUOTED) 
      result = nextUnquotedValue();
     else if (p == PEEKED_SINGLE_QUOTED) 
      result = nextQuotedValue('\\'');
     else if (p == PEEKED_DOUBLE_QUOTED) 
      result = nextQuotedValue('"');
     else if (p == PEEKED_BUFFERED) 
      result = peekedString;
      peekedString = null;
     else if (p == PEEKED_LONG) 
      result = Long.toString(peekedLong);
     else if (p == PEEKED_NUMBER) 
      result = new String(buffer, pos, peekedNumberLength);
      pos += peekedNumberLength;
     else 
      throw new IllegalStateException("Expected a string but was " + peek()
          + " at line " + getLineNumber() + " column " + getColumnNumber());
    
    peeked = PEEKED_NONE;
    return result;
  

第3行代码,p=PEEKED_NONE,程序运行第4行,代码再次进入doPeek()。

private int doPeek() throws IOException 
    int peekStack = stack[stackSize - 1];
    if (peekStack == JsonScope.EMPTY_ARRAY) 
      stack[stackSize - 1] = JsonScope.NONEMPTY_ARRAY;
     else if (peekStack == JsonScope.NONEMPTY_ARRAY) 
      ...
     else if (peekStack == JsonScope.EMPTY_OBJECT || peekStack == JsonScope.NONEMPTY_OBJECT) 
      ...
     else if (peekStack == JsonScope.DANGLING_NAME) 
      stack[stackSize - 1] = JsonScope.NONEMPTY_OBJECT;
      // Look for a colon before the value.
      int c = nextNonWhitespace(true);
      switch (c) 
      case ':':
        break;
      case '=':
        checkLenient();
        if ((pos < limit || fillBuffer(1)) && buffer[pos] == '>') 
          pos++;
        
        break;
      default:
        throw syntaxError("Expected ':'");
      
     else if (peekStack == JsonScope.EMPTY_DOCUMENT) 
      ...
     else if (peekStack == JsonScope.NONEMPTY_DOCUMENT) 
      ...
     else if (peekStack == JsonScope.CLOSED) 
      throw new IllegalStateException("JsonReader is closed");
    

    int c = nextNonWhitespace(true);
    switch (c) 
    case ']':
      if (peekStack == JsonScope.EMPTY_ARRAY) 
        return peeked = PEEKED_END_ARRAY;
      
      // fall-through to handle ",]"
    case ';':
    case ',':
      ...
    case '\\'':
      ...
    case '"':
      if (stackSize == 1) 
        checkLenient();
      
      return peeked = PEEKED_DOUBLE_QUOTED;
    case '[':
      return peeked = PEEKED_BEGIN_ARRAY;
    case '':
      return peeked = PEEKED_BEGIN_OBJECT;
    default:
      pos--; // Don't consume the first character in a literal value.
    
    ...
  

stackSize = 2,peekStack=stack[1]=JsonScope.DANGLING_NAME。
程序运行到第10行,stack[1]=JsonScope.NONEMPTY_OBJECT

stack数组value
stack[0]JsonScope.EMPTY_DOCUMENT JsonScope.NONEMPTY_DOCUMENT
stack[1]JsonScope.EMPTY_OBJECT
stack[1]JsonScope.DANGLING_NAME
stack[1]JsonScope.NONEMPTY_OBJECT
int c = nextNonWhitespace(true);
private int nextNonWhitespace(boolean throwOnEof) throws IOException 
    char[] buffer = this.buffer;
    int p = pos;
    int l = limit;
    while (true) 
      if (p == l) 
        ...
      

      int c = buffer[p++];
      if (c == '\\n') 
        lineNumber++;
        lineStart = p;
        continue;
       else if (c == ' ' || c == '\\r' || c == '\\t') 
        continue;
      

      if (c == '/') 
        ...
       else if (c == '#') 
        ...
       else 
        pos = p;
        return c;
      
    
    ...
  

p=pos=7,l=limit=30,程序运行到第10行,c=buffer[7]=58,在ASCII码中是冒号:同时,p加1,p=8
程序运行到第24行,pos=p=8,将c作为返回值返回到doPeek()方法中。

012345678
name:

doPeek()方法中,运行到第12行,c=58,也就是冒号,程序运行第14行,15行,跳出switch语句。程序运行到第33行,再次运行nextNonWhitespace()方法。

private int nextNonWhitespace(boolean throwOnEof) throws IOException 
    char[] buffer = this.buffer;
    int p = pos;
    int l = limit;
    while (true) 
      if (p == l) 
        ...
      

      int c = buffer[p++];
      if (c == '\\n') 
        lineNumber++;
        lineStart = p;
        continue;
       else if (c == ' ' || c == '\\r' || c == '\\t') 
        continue;
      

      if (c == '/') 
        ...
       else if (c == '#') 
        ...
       else 
        pos = p;
        return c;
      
    
    ...
  

第10行

int c = buffer[p++];

p=8,c=buffer[8]=34,也就是双引号,p加1,p=9

0123456789
name:

方法再次回到doPeek()方法,第33行

int c = nextNonWhitespace(true);

第45~49行,

case '"':
  if (stackSize == 1) 
    checkLenient();
  
  return peeked = PEEKED_DOUBLE_QUOTED;

stackSize=2,将PEEKED_DOUBLE_QUOTED赋值给peeked,方法将peeked返回。

peeked的值
PEEKED_NONE
PEEKED_BEGIN_OBJECT
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE
PEEKED_DOUBLE_QUOTED

方法回到nextString()方法的第4行,继续往下运行,执行到第12行

result = nextQuotedValue('"');
 private String nextQuotedValue(char quote) throws IOException 
    // Like nextNonWhitespace, this uses locals 'p' and 'l' to save inner-loop field access.
    char[] buffer = this.buffer;
    StringBuilder builder = new StringBuilder();
    while (true) 
      int p = pos;
      int l = limit;
      /* the index of the first character not yet appended to the builder. */
      int start = p;
      while (p < l) 
        int c = buffer[p++];

        if (c == quote) 
          pos = p;
          builder.append(buffer, start, p - start - 1);
          return builder.toString();
         else if (c == '\\\\') 
          pos = p;
          builder.append(buffer, start, p - start - 1);
          builder.append(readEscapeCharacter());
          p = pos;
          l = limit;
          start = p;
         else if (c == '\\n') 
          lineNumber++;
          lineStart = p;
        
      

      builder.append(buffer, start, p - start);
      pos = p;
      if (!fillBuffer(1)) 
        throw syntaxError("Unterminated string");
      
    
  

第9行,start=p=9,进入while循环,第11行

 int c = buffer[p++];
 builder.append(buffer, start, p - start - 1);

当p=17时,c=buffer[17]=34,也就是双引号,p加1,p=18
p-start-1=18-9-1=8

0123456789101112131415161718
name:wisely

将“王成wisely”这8个字符作为返回值返回到nextString()方法中的第12行,

result = nextQuotedValue('"');

result = “王成wisely”
之后,程序运行到第25行

peeked = PEEKED_NONE;
peeked的值
PEEKED_NONE
PEEKED_BEGIN_OBJECT
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE
PEEKED_DOUBLE_QUOTED
PEEKED_NONE

hasNext()

程序再次执行hasNext()方法
调用过程hasNext()–>doPeek(),如下

private int doPeek() throws IOException 
    int peekStack = stack[stackSize - 1];
    if (peekStack == JsonScope.EMPTY_ARRAY) 
      stack[stackSize - 1] = JsonScope.NONEMPTY_ARRAY;
     else if (peekStack == JsonScope.NONEMPTY_ARRAY) 
      ...
     else if (peekStack == JsonScope.EMPTY_OBJECT || peekStack == JsonScope.NONEMPTY_OBJECT) 
      stack[stackSize - 1] = JsonScope.DANGLING_NAME;
      // Look for a comma before the next element.
      if (peekStack == JsonScope.NONEMPTY_OBJECT) 
        int c = nextNonWhitespace(true);
        switch (c) 
        case '':
          return peeked = PEEKED_END_OBJECT;
        case ';':
          checkLenient(); // fall-through
        case ',':
          break;
        default:
          throw syntaxError("Unterminated object");
        
      
      int c = nextNonWhitespace(true);
      switch (c) 
      case '"':
        return peeked = PEEKED_DOUBLE_QUOTED_NAME;
      ...
     else if (peekStack == JsonScope.DANGLING_NAME) 
      ...
     else if (peekStack == JsonScope.EMPTY_DOCUMENT) 
      ...
     else if (peekStack == JsonScope.NONEMPTY_DOCUMENT) 
      ...
     else if (peekStack == JsonScope.CLOSED) 
      ...
    
     ...

  

第11行,

int c = nextNonWhitespace(true);

c=44,也就是逗号。同时p=19

012345678910111213141516171819
name:wisely,

程序继续执行,运行到第23行

int c = nextNonWhitespace(true);

c=34,也就是双引号,同时p=20

01234567891011121314151617181920
name:wisely,

整个doPeek()方法运行完毕前,peeked被重新赋值为PEEKED_DOUBLE_QUOTED_NAME。

peeked的值
PEEKED_NONE
PEEKED_BEGIN_OBJECT
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE
PEEKED_DOUBLE_QUOTED
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME

程序执行回hasNext()方法,返回true。

nextName()


第二次运行,调用过程依旧,nextName()–>nextQuotedValue(‘”’)

private String nextQuotedValue(char quote) throws IOException 
    // Like nextNonWhitespace, this uses locals 'p' and 'l' to save inner-loop field access.
    char[] buffer = this.buffer;
    StringBuilder builder = new StringBuilder();
    while (true) 
      int p = pos;
      int l = limit;
      /* the index of the first character not yet appended to the builder. */
      int start = p;
      while (p < l) 
        int c = buffer[p++];

        if (c == quote) 
          pos = p;
          builder.append(buffer, start, p - start - 1);
          return builder.toString();
         else if (c == '\\\\') 
          pos = p;
          builder.append(buffer, start, p - start - 1);
          builder.append(readEscapeCharacter());
          p = pos;
          l = limit;
          start = p;
         else if (c == '\\n') 
          lineNumber++;
          lineStart = p;
        
      

      builder.append(buffer, start, p - start);
      pos = p;
      if (!fillBuffer(1)) 
        throw syntaxError("Unterminated string");
      
    
  

start=20,当p=23时,int c = buffer[23]=34,也就是双引号,同时p加1,p=24。

builder.append(buffer, start, p - start - 1);

p-start-1=24-20-1=3。

01234567891011121314
name:wise
15161718192021222324
ly,age

最终nextName()方法返回age3个字符,并且将peeked重置为PEEKED_NONE。

peeked的值
PEEKED_NONE
PEEKED_BEGIN_OBJECT
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE
PEEKED_DOUBLE_QUOTED
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE

nextInt()


public int nextInt() throws IOException 
    int p = peeked;
    if (p == PEEKED_NONE) 
      p = doPeek();
    

    int result;
    if (p == PEEKED_LONG) 
      ...
    

    if (p == PEEKED_NUMBER) 
      ...
     else if (p == PEEKED_SINGLE_QUOTED || p == PEEKED_DOUBLE_QUOTED) 
      peekedString = nextQuotedValue(p == PEEKED_SINGLE_QUOTED ? '\\'' : '"');
      try 
        result = Integer.parseInt(peekedString);
        peeked = PEEKED_NONE;
        return result;
       catch (NumberFormatException ignored) 
        // Fall back to parse as a double below.
      
     else 
      throw new IllegalStateException("Expected an int but was " + peek()
          + " at line " + getLineNumber() + " column " + getColumnNumber());
    

    peeked = PEEKED_BUFFERED;
    double asDouble = Double.parseDouble(peekedString); // don't catch this NumberFormatException.
    result = (int) asDouble;
    if (result != asDouble)  // Make sure no precision was lost casting to 'int'.
      throw new NumberFormatException("Expected an int but was " + peekedString
          + " at line " + getLineNumber() + " column " + getColumnNumber());
    
    peekedString = null;
    peeked = PEEKED_NONE;
    return result;
  

方法进入调用了doPeek()方法

private int doPeek() throws IOException 
    int peekStack = stack[stackSize - 1];
    if (peekStack == JsonScope.EMPTY_ARRAY) 
      stack[stackSize - 1] = JsonScope.NONEMPTY_ARRAY;
     else if (peekStack == JsonScope.NONEMPTY_ARRAY) 
      ...
      
     else if (peekStack == JsonScope.EMPTY_OBJECT || peekStack == JsonScope.NONEMPTY_OBJECT) 
      ...
     else if (peekStack == JsonScope.DANGLING_NAME) 
      stack[stackSize - 1] = JsonScope.NONEMPTY_OBJECT;
      // Look for a colon before the value.
      int c = nextNonWhitespace(true);
      switch (c) 
      case ':':
        break;
      case '=':
        ...
      
     else if (peekStack == JsonScope.EMPTY_DOCUMENT) 
      ...
     else if (peekStack == JsonScope.NONEMPTY_DOCUMENT) 
      ...
     else if (peekStack == JsonScope.CLOSED) 
      ...
    

    int c = nextNonWhitespace(true);
    switch (c) 
    case ']':
      ...
    case ';':
    case ',':
      ...
    case '\\'':
      ...
    case '"':
      if (stackSize == 1) 
        checkLenient();
      
      return peeked = PEEKED_DOUBLE_QUOTED;
    case '[':
      return peeked = PEEKED_BEGIN_ARRAY;
    case '':
      return peeked = PEEKED_BEGIN_OBJECT;
    default:
      pos--; // Don't consume the first character in a literal value.
    
    ...
  

peekStack=stack[1]=JsonScope.JsonScope.DANGLING_NAME。
代码运行到第11行,为stack[1]赋值为JsonScope.NONEMPTY_OBJECT。

stack数组value
stack[0]JsonScope.EMPTY_DOCUMENT JsonScope.NONEMPTY_DOCUMENT
stack[1]JsonScope.EMPTY_OBJECT
stack[1]JsonScope.DANGLING_NAME
stack[1]JsonScope.NONEMPTY_OBJECT
stack[1]JsonScope.DANGLING_NAME
stack[1]JsonScope.NONEMPTY_OBJECT

程序运行到第13行,

int c = nextNonWhitespace(true);

获取到的c=58,也就是冒号:之后跳出switch语句再次运行了一个同样的语句,获得了一个c,c=34,也就是双引号。
然后为peeked重新赋值为PEEKED_DOUBLE_QUOTED,退出doPeek()方法

peeked的值
PEEKED_NONE
PEEKED_BEGIN_OBJECT
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE
PEEKED_DOUBLE_QUOTED
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE
PEEKED_DOUBLE_QUOTED

代码回到nextInt中,继续运行第15行,最终又调用了nextQuotedValue(“)方法。

peekedString = nextQuotedValue(p == PEEKED_SINGLE_QUOTED ? '\\'' : '"');

在nextQuotedValue()方法运行时,start=26,p=28时,c=34,也就是双引号,之后p加1,p=29,最终p-start-1=2,也就是24。

01234567891011121314
name:wise
151617181920212223242526272829
ly,age:24

之后为peeked赋值为PEEKED_NONE,

peeked的值
PEEKED_NONE
PEEKED_BEGIN_OBJECT
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE
PEEKED_DOUBLE_QUOTED
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE
PEEKED_DOUBLE_QUOTED
PEEKED_NONE

hasNext()


最后一次调用hasNext()方法。
hasNext()–>doPeek()–>nextNonWhitespace()
通过nextNonWhitespace方法获取到了一个右大括号,在doPeek()方法中重置peeked值为peeked = PEEKED_END_OBJECT。之后代码再返回到hasNext()中,返回false。

01234567891011121314
name:wise
151617181920212223242526272829
ly,age:24
peeked的值
PEEKED_NONE
PEEKED_BEGIN_OBJECT
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE
PEEKED_DOUBLE_QUOTED
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE
PEEKED_DOUBLE_QUOTED
PEEKED_NONE
PEEKED_END_OBJECT

endObject()

public void endObject() throws IOException 
    int p = peeked;
    if (p == PEEKED_NONE) 
      p = doPeek();
    
    if (p == PEEKED_END_OBJECT) 
      stackSize--;
      peeked = PEEKED_NONE;
     else 
      throw new IllegalStateException("Expected END_OBJECT but was " + peek()
          + " at line " + getLineNumber() + " column " + getColumnNumber());
    
  

第7行时,将stackSize-1,变为了1。最后将peeked重置为PEEKED_NONE。

peeked的值
PEEKED_NONE
PEEKED_BEGIN_OBJECT
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE
PEEKED_DOUBLE_QUOTED
PEEKED_NONE
PEEKED_DOUBLE_QUOTED_NAME
PEEKED_NONE
PEEKED_DOUBLE_QUOTED
PEEKED_NONE
PEEKED_END_OBJECT
PEEKED_NONE

以上是关于Gson全解析之二:JsonReader的其它方法的主要内容,如果未能解决你的问题,请参考以下文章

JsonReader 无法正确解析字符串数组

我如何查看从 GSON JsonReader 收到了多少字节

Gson源码解析

Gson源码解析

Gson使用google的JsonReader读取Json文件并转化成对象

使用 GSON 的 JsonReader 流式传输 Json 文件时,您可以将对象转储为字符串吗?