JsonReader - 读取数组抛出 Expected a name but was NULL
JsonReader - reading an array throws Expected a name but was NULL
我正在使用 JsonReader 来解析一些 JSON 数据。这是一大堆类似结构的元素:
[
{
"type":"duel",
"discipline":"leagueoflegends",
"tournament_id":"57ee13fe140ba0cd2a8b4593",
"opponents":[
{
"participant":null,
"forfeit":false,
"number":1,
"result":1,
"score":3
},
{
"participant":null,
"forfeit":false,
"number":2,
"result":3,
"score":2
}
],
"id":"58078b2770cb49c45b8b45bf",
"status":"completed",
"number":1,
"stage_number":1,
"group_number":1,
"round_number":1,
"date":"2016-10-01T05:00:00+0300",
"timezone":"Europe/Helsinki",
"match_format":null
},
...
]
此数组中有数百个相似元素。我只需要每个元素的一些数据,我编写了类似于 this:
的代码
public List<Match> readJsonStream(InputStream in) throws IOException {
JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
try {
return readMatchesArray(reader);
} finally {
reader.close();
}
}
public List<Match> readMatchesArray(JsonReader reader) throws IOException {
List<Match> matches = new ArrayList<>();
reader.beginArray();
while (reader.hasNext()) {
matches.add(readMatch(reader));
}
reader.endArray();
return matches;
}
public Match readMatch(JsonReader reader) throws IOException {
String status = null, date = null, time = null;
Match.Bracket bracket = null;
int id = -1, round = -1;
Match.Team team1 = null, team2 = null;
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
switch (name) {
case "number":
id = reader.nextInt();
break;
case "status":
status = reader.nextString().toUpperCase();
break;
case "group_number":
if (reader.nextInt() == 1) {
bracket = WINNERS;
} else if (reader.nextInt() == 2) {
bracket = LOSERS;
}
break;
case "round_number":
round = reader.nextInt();
break;
case "date":
try {
String tempDateRaw = reader.nextString();
String[] tempDate = tempDateRaw.split("T");
String[] tempTime = tempDate[1].split(":");
date = tempDate[0];
time = tempTime[0] + ":" + tempTime[1];
} catch (IllegalStateException e) {
date = null;
time = null;
}
break;
case "opponents":
int counter = 0;
reader.beginArray();
while (reader.hasNext()) {
if (counter == 0) {
team1 = readTeam(reader);
} else {
team2 = readTeam(reader);
}
counter++;
}
reader.endArray();
break;
default:
reader.skipValue();
break;
}
}
reader.endObject();
return new Match(team1, team2, id, round, bracket, status, date, time);
}
public Match.Team readTeam(JsonReader reader) throws IOException {
String teamName = null;
int score = -1;
boolean winner = false;
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName(); //this is where the error occurs
switch (name) {
case "participant":
if(reader.peek() != JsonToken.NULL) {
teamName = reader.nextString();
}
else {
teamName = null;
}
break;
case "score":
if(reader.peek() != JsonToken.NULL) {
score = reader.nextInt();
}
else {
score = -1;
}
break;
case "result":
if(reader.peek() != JsonToken.NULL) {
winner = reader.nextInt() == 1;
}
else {
winner = false;
}
break;
default:
reader.skipValue();
break;
}
}
reader.endObject();
return new Match.Team(teamName, score, winner);
}
但是,当我尝试解析对手数组时,我在 readTeam() 中遇到了一个错误 需要一个名称,但却是 NULL 我很困惑为什么会这样正在发生。
起初我不知道 peek() 所以在我使用的 readMatch() 方法中 try/catch,我必须更改它,但它应该与问题无关。我找不到关于这个特定错误的任何信息,还有很多关于其他类似错误的主题(预期名称是 string/int/whatever),但在这里我找不到它不起作用的原因。您有解决方法吗?
好吧,我找到了解决办法,和我想的一样,比我想象的要简单。所以基本上当我检查空值时,就像这样:
if(reader.peek() != JsonToken.NULL) {
teamName = reader.nextString();
}
else {
teamName = null;
}
所谓的 "reader cursor" 不会移动,所以它基本上停留在 teamName 的值上(在本例中)。所以最简单的解决方案是将 reader.skipValue();
放在 else
块中。我还在我的代码中发现了另一个错误,在 case "group_number"
中,我实际上将上述 "cursor" 移动了两次,但解决方案是显而易见的。希望对某人有所帮助。
你也应该消耗 null
个代币,调用 nextNull()
或 skipValue()
,否则 Reader
不会前进并坚持这个 null
.例如:
case "result":
if(reader.peek() != JsonToken.NULL) {
winner = reader.nextInt() == 1;
} else {
winner = false;
reader.nextNull(); // note on this
}
break;
https://developer.android.com/reference/android/util/JsonReader
Null literals can be consumed using either nextNull() or skipValue().
我正在使用 JsonReader 来解析一些 JSON 数据。这是一大堆类似结构的元素:
[
{
"type":"duel",
"discipline":"leagueoflegends",
"tournament_id":"57ee13fe140ba0cd2a8b4593",
"opponents":[
{
"participant":null,
"forfeit":false,
"number":1,
"result":1,
"score":3
},
{
"participant":null,
"forfeit":false,
"number":2,
"result":3,
"score":2
}
],
"id":"58078b2770cb49c45b8b45bf",
"status":"completed",
"number":1,
"stage_number":1,
"group_number":1,
"round_number":1,
"date":"2016-10-01T05:00:00+0300",
"timezone":"Europe/Helsinki",
"match_format":null
},
...
]
此数组中有数百个相似元素。我只需要每个元素的一些数据,我编写了类似于 this:
的代码public List<Match> readJsonStream(InputStream in) throws IOException {
JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
try {
return readMatchesArray(reader);
} finally {
reader.close();
}
}
public List<Match> readMatchesArray(JsonReader reader) throws IOException {
List<Match> matches = new ArrayList<>();
reader.beginArray();
while (reader.hasNext()) {
matches.add(readMatch(reader));
}
reader.endArray();
return matches;
}
public Match readMatch(JsonReader reader) throws IOException {
String status = null, date = null, time = null;
Match.Bracket bracket = null;
int id = -1, round = -1;
Match.Team team1 = null, team2 = null;
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
switch (name) {
case "number":
id = reader.nextInt();
break;
case "status":
status = reader.nextString().toUpperCase();
break;
case "group_number":
if (reader.nextInt() == 1) {
bracket = WINNERS;
} else if (reader.nextInt() == 2) {
bracket = LOSERS;
}
break;
case "round_number":
round = reader.nextInt();
break;
case "date":
try {
String tempDateRaw = reader.nextString();
String[] tempDate = tempDateRaw.split("T");
String[] tempTime = tempDate[1].split(":");
date = tempDate[0];
time = tempTime[0] + ":" + tempTime[1];
} catch (IllegalStateException e) {
date = null;
time = null;
}
break;
case "opponents":
int counter = 0;
reader.beginArray();
while (reader.hasNext()) {
if (counter == 0) {
team1 = readTeam(reader);
} else {
team2 = readTeam(reader);
}
counter++;
}
reader.endArray();
break;
default:
reader.skipValue();
break;
}
}
reader.endObject();
return new Match(team1, team2, id, round, bracket, status, date, time);
}
public Match.Team readTeam(JsonReader reader) throws IOException {
String teamName = null;
int score = -1;
boolean winner = false;
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName(); //this is where the error occurs
switch (name) {
case "participant":
if(reader.peek() != JsonToken.NULL) {
teamName = reader.nextString();
}
else {
teamName = null;
}
break;
case "score":
if(reader.peek() != JsonToken.NULL) {
score = reader.nextInt();
}
else {
score = -1;
}
break;
case "result":
if(reader.peek() != JsonToken.NULL) {
winner = reader.nextInt() == 1;
}
else {
winner = false;
}
break;
default:
reader.skipValue();
break;
}
}
reader.endObject();
return new Match.Team(teamName, score, winner);
}
但是,当我尝试解析对手数组时,我在 readTeam() 中遇到了一个错误 需要一个名称,但却是 NULL 我很困惑为什么会这样正在发生。
起初我不知道 peek() 所以在我使用的 readMatch() 方法中 try/catch,我必须更改它,但它应该与问题无关。我找不到关于这个特定错误的任何信息,还有很多关于其他类似错误的主题(预期名称是 string/int/whatever),但在这里我找不到它不起作用的原因。您有解决方法吗?
好吧,我找到了解决办法,和我想的一样,比我想象的要简单。所以基本上当我检查空值时,就像这样:
if(reader.peek() != JsonToken.NULL) {
teamName = reader.nextString();
}
else {
teamName = null;
}
所谓的 "reader cursor" 不会移动,所以它基本上停留在 teamName 的值上(在本例中)。所以最简单的解决方案是将 reader.skipValue();
放在 else
块中。我还在我的代码中发现了另一个错误,在 case "group_number"
中,我实际上将上述 "cursor" 移动了两次,但解决方案是显而易见的。希望对某人有所帮助。
你也应该消耗 null
个代币,调用 nextNull()
或 skipValue()
,否则 Reader
不会前进并坚持这个 null
.例如:
case "result":
if(reader.peek() != JsonToken.NULL) {
winner = reader.nextInt() == 1;
} else {
winner = false;
reader.nextNull(); // note on this
}
break;
https://developer.android.com/reference/android/util/JsonReader
Null literals can be consumed using either nextNull() or skipValue().