3

I have a JSON like:

{"aData":

{"tournaments":

{"new":[

{"token":"1-token", "prio":"6", "status":"inactive", ..., "_timeCreated":"2014-04-14 14:44:49", "_timeChanged":"2014-08-08 12:30:20"},

{"token":"2-token","prio":"8","status":"inactive",...}

] }

}

}

the JSON file is 8 MB big and is valid, as it can be parsed with default new JSONObject(str) or within a Volley's JsonObjectRequest.

The code I use:

 reader = new JsonReader( new InputStreamReader( am.open( "updatedata.json" ) ) );
 reader.setLenient( true );
 while( reader.hasNext() ){
   eachToken( reader );
   Log.i( TAG, "has next " + reader.hasNext() );
 }

private boolean eachToken( JsonReader reader ) throws IOException {
  JsonToken token = reader.peek();
  switch( token ){
    case BEGIN_ARRAY:
      reader.beginArray();
      Log.i( TAG, "array <<" );
      break;
    case END_ARRAY:
      reader.endArray();
      Log.i( TAG, "array >>" );
      break;
    case BEGIN_OBJECT:
      reader.beginObject();
      Log.i( TAG, "{" );
      break;
    case END_OBJECT:
      reader.endObject();
      Log.i( TAG, "}" );
      break;
    case NAME:
      String name = reader.nextName();
      Log.i( TAG, name );
      break;
    case STRING:
      String s = reader.nextString();
      Log.i( TAG, s );
      break;
    case NUMBER:
      int n = reader.nextInt();
      Log.i( TAG, "" + n );
      break;
    case BOOLEAN:
      boolean b = reader.nextBoolean();
      Log.i( TAG, "" + b );
      break;
    case NULL:
      reader.nextNull();
      Log.i( TAG, "null" );
      break;
    case END_DOCUMENT:
      Log.i( TAG, "end doc" );
      return false;
    default:
      Log.i( TAG, token.toString() );
  }
  return true;
}

the problem is, that the case END_OBJECT is never reached. It prints the following into the logcat:

  01-06 13:30:32.817: I/DataService(1819): {
  01-06 13:30:32.817: I/DataService(1819): has next true
  01-06 13:30:32.817: I/DataService(1819): aData
  01-06 13:30:32.817: I/DataService(1819): has next true
  01-06 13:30:32.817: I/DataService(1819): {
  01-06 13:30:32.817: I/DataService(1819): has next true
  01-06 13:30:32.817: I/DataService(1819): tournaments
  01-06 13:30:32.817: I/DataService(1819): has next true
  01-06 13:30:32.817: I/DataService(1819): {
  01-06 13:30:32.817: I/DataService(1819): has next true
  01-06 13:30:32.817: I/DataService(1819): new
  01-06 13:30:32.817: I/DataService(1819): has next true
  01-06 13:30:32.817: I/DataService(1819): array <<
  01-06 13:30:32.817: I/DataService(1819): has next true
  01-06 13:30:32.817: I/DataService(1819): {
  01-06 13:30:32.817: I/DataService(1819): has next true
  01-06 13:30:32.827: I/DataService(1819): token
  01-06 13:30:32.827: I/DataService(1819): has next true
  01-06 13:30:32.827: I/DataService(1819): 1-token
  01-06 13:30:32.827: I/DataService(1819): has next true
  01-06 13:30:32.827: I/DataService(1819): prio
  01-06 13:30:32.827: I/DataService(1819): has next true
  01-06 13:30:32.827: I/DataService(1819): 6
  01-06 13:30:32.827: I/DataService(1819): has next true
  01-06 13:30:32.827: I/DataService(1819): status
  01-06 13:30:32.827: I/DataService(1819): has next true
  01-06 13:30:32.827: I/DataService(1819): inactive
  01-06 13:30:32.837: I/DataService(1819): has next true
  01-06 13:30:32.837: I/DataService(1819): _timeCreated
  01-06 13:30:32.837: I/DataService(1819): has next true
  01-06 13:30:32.837: I/DataService(1819): 2014-04-14 14:44:49
  01-06 13:30:32.837: I/DataService(1819): has next true
  01-06 13:30:32.837: I/DataService(1819): _timeChanged
  01-06 13:30:32.837: I/DataService(1819): has next true
  01-06 13:30:32.837: I/DataService(1819): 2014-08-08 12:30:20
  01-06 13:30:32.837: I/DataService(1819): has next false

so, it reaches the "_timeChanged":"2014-08-08 12:30:20" of the 1st object, and then reader.hasNext() turns false instead of moving to the new BEGIN_OBJECT token.

what am I missing? TIA

injecteer
  • 20,038
  • 4
  • 45
  • 89
  • I have had problems with GSON recognising (non-json) arrays within json, that is square bracket arrays. I found that I have to create a class for the json api response that included MyClass[] array classes. Could this be the issue? – TTransmit Jan 06 '15 at 13:17
  • why `[]` arrays are non-json? – injecteer Jan 06 '15 at 15:23
  • There is an alternative way of structuring array data in json that I have seen used in some projects that doesn't use square brackets. I always called this a json array and square brackets arrays I just called arrays. It looks like it may only be me who makes this distinction. In attempting to make my answer clearer, I made it less clear, sorry. – TTransmit Jan 06 '15 at 16:05

2 Answers2

3

hasNext() says "Returns true if the current array or object has another element." In your case, when it hits the end of an object or array hasNext() is false so case END_ARRAY and case END_OBJECT don't get called.

This may work:

while( reader.hasNext() 
        || reader.peek() == END_ARRAY 
        || reader.peek() == END_OBJECT ){
    eachToken( reader );
    Log.i( TAG, "has next " + reader.hasNext() );
}

This is essentially the same as Joey's answer but wouldn't fit in a comment.

TTransmit
  • 3,270
  • 2
  • 28
  • 43
2

I guess the issue might be in the way you handle the Data

If you look at the JavaDoc for JsonReader it especially defines that you need to consume array brackets ..

Within array handling methods, first call beginArray() to consume the array's opening bracket. Then create a while loop that accumulates values, terminating when hasNext() is false. Finally, read the array's closing bracket by calling endArray().

So hasNext() is false after the array is finished ...

Joey
  • 1,349
  • 14
  • 26
  • hmmm, I'm getting `hasNext() == false` already at the end of the 1st element of the array, way before the array finishes... – injecteer Jan 06 '15 at 16:10