上篇文章的示例代码
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(<