java - JsonReader - 读取数组抛出预期名称但为 NULL

标签 java android json parsing jsonreader

我正在使用 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),但在这里我无法完全找到它不起作用的原因。您有解决办法吗?

最佳答案

您也应该使用 null token ,调用 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().

关于java - JsonReader - 读取数组抛出预期名称但为 NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40451938/

相关文章:

java - 为什么 Jave 方法不返回一个元组而不是一个对象引用(或 null)?

java - 从字符串中解析日期

java - 尝试通过 MySQL 正确保存/加载数组

java - 在按钮上的 fragment 中使用弹出菜单

php - json解码函数后奇怪的sql插入

json - 缺少 d3 连接 choropleth map 中数据的步骤

java - 使用异步任务 (Json) 更新 ListView

java - 为什么 inc/dec channel 不执行任何操作?

java - Android Widget 上的 RemoteViews setViewVisibility

android - 在 Canvas android上绘制垂直线给定线