2016-11-06 3 views
0

J'utilise JsonReader pour analyser des données JSON. C'est un grand nombre d'éléments de structure similaire:JsonReader - lire un tableau throws un nom mais Expected était NULL

[ 
    { 
     "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 
    }, 
    ... 
] 

Il y a des centaines d'éléments similaires dans ce tableau. Je ne ai besoin des données de chaque élément et je l'ai écrit un code similaire à 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); 
} 

Cependant, quand je suis en train d'analyser le tableau des adversaires que j'ai une erreur dans readTeam() Expected un nom, mais était NULL et je suis très confus pourquoi est ce qui se passe. Au début je ne connaissais pas le peek() donc dans la méthode readMatch() j'ai utilisé try/catch, je dois le changer, mais cela ne devrait pas être pertinent pour le problème. Je n'ai rien trouvé à propos de cette erreur particulière, il y a beaucoup de sujets concernant d'autres erreurs similaires (le nom attendu est string/int/quelquechose) mais ici je n'arrive pas à trouver la raison pour laquelle ça ne marche pas. Avez-vous des idées pour y remédier?

+0

Y a-t-il une raison pour laquelle vous n'utilisez pas 'GSON' pour analyser le' JSON'? –

+0

Eh bien, pas vraiment. Je suis encore débutant en Java et un newb complet sous Android, et c'est la première chose que j'ai vu concernant l'analyse de JSON. Précédemment, j'ai simplement utilisé StringBuilder et utilisé getJSONObject(), mais comme le fichier est trop gros, j'ai manqué de mémoire. Je suppose que je pourrais essayer GSON, mais d'abord je n'ai pas beaucoup de temps et en second lieu, je suis assez confiant que mon problème est facilement résoluble, je ne peux pas trouver la cause. – tuptus

+0

Jetez un oeil à 'GSON' quand vous trouvez l'heure. Bonne chance. –

Répondre

0

D'accord, j'ai trouvé une solution, tout comme je pensais, il était plus simple que prévu. Donc, fondamentalement, quand je vérifie les valeurs NULL, comme ceci:

if(reader.peek() != JsonToken.NULL) { 
    teamName = reader.nextString(); 
} 
else { 
    teamName = null; 
} 

le soi-disant « curseur de lecture » ne bouge pas, il est donc essentiellement collé sur la valeur de la teamname (dans ce cas). Donc, la solution la plus simple est de simplement mettre reader.skipValue(); dans le bloc else. J'ai aussi trouvé un autre bug dans mon code, en case "group_number" où je déplace deux fois le "curseur" mentionné ci-dessus, mais la solution est évidente. J'espère que cela sera utile pour quelqu'un.