joy
joy copied to clipboard
Iterating over an array inside other JSON can run off the end of the array and through the rest of the JSON
Say you have some JSON with an array somewhere inside, like this:
{"a": [1], "b": "the end"}
If you parse to the start of the array, then call parser.getArrayStream().iterator(), you get an iterator, which i believe should iterate over the contents of the array, and then stop. And indeed, you do. But if you then call hasNext() on the iterator again, it surprisingly returns true, and if you call next(), it returns a JsonValue containing the string "b" - this is the next object key after the end of the array!
Here's a JUnit 5 test:
try (JsonParser parser = Json.createParser(new StringReader("{\"a\": [1], \"b\": \"the end\"}"))) {
assertThat(parser.next(), equalTo(JsonParser.Event.START_OBJECT));
assertThat(parser.next(), equalTo(JsonParser.Event.KEY_NAME));
assertThat(parser.getString(), equalTo("a"));
assertThat(parser.next(), equalTo(JsonParser.Event.START_ARRAY));
Iterator<JsonValue> iterator = parser.getArrayStream().iterator();
assertThat(iterator.hasNext(), equalTo(true));
assertThat(iterator.next(), equalTo(json.createValue(1)));
assertThat(iterator.hasNext(), equalTo(false));
// this fails because the iterator starts iterating over the outer object!
assertThat(iterator.hasNext(), equalTo(false));
assertThat(parser.next(), equalTo(JsonParser.Event.KEY_NAME));
assertThat(parser.getString(), equalTo("b"));
assertThat(parser.next(), equalTo(JsonParser.Event.VALUE_STRING));
assertThat(parser.getString(), equalTo("the end"));
assertThat(parser.next(), equalTo(JsonParser.Event.END_OBJECT));
}
This also happens when the array is nested inside another array. There, the iterator iterates over the other elements in the outer array.
Using Joy 2.1.0 with OpenJDK 17+35.