I've been looking for example Gson streaming API code, and I see a lot of this style:
reader.beginObject();
while (reader.hasNext()) {
switch(reader.peek()) {
case NAME:
...
case BEGIN_ARRAY:
...
case END_ARRAY:
...
}
reader.endObject();
reader.close();
That code works great when the JSON has only one "top-level" object. The hasNext() loop terminates at the end of that first object. What I need is a loop around that to process ALL the objects. Here's an abbreviated example of my JSON:
{
"meta": {
"disclaimer": "Loren Ipsum",
"terms": "https://myURL/terms/",
"license": "https://myURL/license/",
"last_updated": "2023-03-10",
"totals": {
"skip": 0,
"limit": 12000,
"total": 362818
}
},
"results": [
{"result": "value1"},
{"result": "value2"},
{"result": "value3"},
]
}
This code processes the "meta" object just fine, and never get to the "results" array.
Searched high and low.
Normally you never have to handle
NAMEandEND_ARRAYwhen usingpeek():hasNext()in a loop, and while the result is true callnextName(), followed by a value reading method such asnextInt()(possibly after checking the type withpeek()first).hasNext()then you won't encounter anEND_ARRAYinside the loop.The general structure for reading JSON arrays and objects from a
JsonReaderis:And you can arbitrarily nest this. Here is an example for this, based on your JSON data. The main point of this example is to demonstrate the nesting, the code is not very useful and also quite verbose:
But is it really necessary in your use case to directly read from a
JsonReader? If not, then it would be probably less error-prone to just create model classes matching your JSON data (e.g.class Meta { String disclaimer; URL terms; ... }) and use one of theGson.fromJsonmethods with aReaderas parameter. Internally that will also parse JSON in a streaming way, so the only overhead is that afterwards the complete deserialized object exists in memory. But maybe that is exactly what you need.