上篇文章的示例代码
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] | |
| 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。
| 0 | 1 |
|---|---|
| { | “ |
第24行,pos=p=2,将c作为返回值返回到doPeek()方法中。
doPeek()中运行到第16行
peeked = PEEKED_DOUBLE_QUOTED_NAME;| peeked的值 |
|---|
| 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。
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|
| { | “ | n | a | m | e | “ |
获取到的字符串就是2-6之间的字符拼接而成,也就是name。将name作为返回值返回到nextName()中,程序运行到第17行
peeked = PEEKED_NONE;| peeked的值 |
|---|
| 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] | |
| 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()方法中。
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| { | “ | n | a | m | e | “ | : |
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。
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|
| { | “ | n | a | m | e | “ | : | “ |
方法再次回到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_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
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | |
| { | “ | n | a | m | e | “ | : | “ | 王 | 成 | w | i | s | e | l | y | “ |
将“王成wisely”这8个字符作为返回值返回到nextString()方法中的第12行,
result = nextQuotedValue('"');result = “王成wisely”
之后,程序运行到第25行
peeked = PEEKED_NONE;| peeked的值 |
|---|
| 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。
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | |
| { | “ | n | a | m | e | “ | : | “ | 王 | 成 | w | i | s | e | l | y | “ | , |
程序继续执行,运行到第23行
int c = nextNonWhitespace(true);c=34,也就是双引号,同时p=20
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| { | “ | n | a | m | e | “ | : | “ | 王 | 成 | w | i | s | e | l | y | “ | , | “ |
整个doPeek()方法运行完毕前,peeked被重新赋值为PEEKED_DOUBLE_QUOTED_NAME。
| peeked的值 |
|---|
| 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。
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| { | “ | n | a | m | e | “ | : | “ | 王 | 成 | w | i | s | e |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | |||||
| l | y | “ | , | “ | a | g | e | “ |
最终nextName()方法返回age3个字符,并且将peeked重置为PEEKED_NONE。
| peeked的值 |
|---|
| 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] | |
| stack[1] | JsonScope.NONEMPTY_OBJECT |
程序运行到第13行,
int c = nextNonWhitespace(true);获取到的c=58,也就是冒号:之后跳出switch语句再次运行了一个同样的语句,获得了一个c,c=34,也就是双引号。
然后为peeked重新赋值为PEEKED_DOUBLE_QUOTED,退出doPeek()方法
| peeked的值 |
|---|
| 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。
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| { | “ | n | a | m | e | “ | : | “ | 王 | 成 | w | i | s | e |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| l | y | “ | , | “ | a | g | e | “ | : | “ | 2 | 4 | “ |
之后为peeked赋值为PEEKED_NONE,
| peeked的值 |
|---|
| PEEKED_NONE |
hasNext()
最后一次调用hasNext()方法。
hasNext()–>doPeek()–>nextNonWhitespace()
通过nextNonWhitespace方法获取到了一个右大括号,在doPeek()方法中重置peeked值为peeked = PEEKED_END_OBJECT。之后代码再返回到hasNext()中,返回false。
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| { | “ | n | a | m | e | “ | : | “ | 王 | 成 | w | i | s | e |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| l | y | “ | , | “ | a | g | e | “ | : | “ | 2 | 4 | “ | } |
| peeked的值 |
|---|
| 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 |