Skip to content

Commit 6cb2aa0

Browse files
committed
[java] Make JsonInput.hasNext() idempotent between elements
hasNext() consumed the comma between elements but did not clear the 'container has element' flag, so a second hasNext() before reading the next value threw as if the comma were missing. Iterator-style callers that probe multiple times per element saw spurious failures on valid input like [1,2].
1 parent 1f44b29 commit 6cb2aa0

2 files changed

Lines changed: 43 additions & 0 deletions

File tree

java/src/org/openqa/selenium/json/JsonInput.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@ public boolean hasNext() {
329329
throw new JsonException("Unexpected ',' before first element of container. " + input);
330330
}
331331
input.read();
332+
// We've moved past the separator, so we're once again expecting an element rather than
333+
// another comma. Clear the flag so a repeat hasNext() before reading is a no-op.
334+
clearSeenElement();
332335
skipWhitespace(input);
333336
JsonType afterComma = peek();
334337
// Trailing comma leniency: '[1,]' and '{"a":1,}' are accepted.
@@ -573,6 +576,13 @@ private void markElementRead() {
573576
}
574577
}
575578

579+
private void clearSeenElement() {
580+
if (!containerHasElement.isEmpty()) {
581+
containerHasElement.removeFirst();
582+
containerHasElement.addFirst(false);
583+
}
584+
}
585+
576586
/**
577587
* Read the next element from the JSON input stream, converting with the supplied mapper if it's
578588
* the expected string.

java/test/org/openqa/selenium/json/JsonInputTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,39 @@ void shouldRejectLeadingCommaInArray() {
370370
}
371371
}
372372

373+
@Test
374+
void hasNextIsIdempotentBetweenElementsInArray() {
375+
// Iterator-style probing (peek/hasNext repeatedly before reading) must not falsely fail
376+
// once hasNext() has already consumed the comma before the next element.
377+
try (JsonInput input = newInput("[1,2]")) {
378+
input.beginArray();
379+
assertThat(input.hasNext()).isTrue();
380+
assertThat(input.nextNumber()).isEqualTo(1L);
381+
assertThat(input.hasNext()).isTrue();
382+
assertThat(input.hasNext()).isTrue();
383+
assertThat(input.nextNumber()).isEqualTo(2L);
384+
assertThat(input.hasNext()).isFalse();
385+
assertThat(input.hasNext()).isFalse();
386+
input.endArray();
387+
}
388+
}
389+
390+
@Test
391+
void hasNextIsIdempotentBetweenEntriesInObject() {
392+
try (JsonInput input = newInput("{\"a\":1,\"b\":2}")) {
393+
input.beginObject();
394+
assertThat(input.hasNext()).isTrue();
395+
assertThat(input.nextName()).isEqualTo("a");
396+
assertThat(input.nextNumber()).isEqualTo(1L);
397+
assertThat(input.hasNext()).isTrue();
398+
assertThat(input.hasNext()).isTrue();
399+
assertThat(input.nextName()).isEqualTo("b");
400+
assertThat(input.nextNumber()).isEqualTo(2L);
401+
assertThat(input.hasNext()).isFalse();
402+
input.endObject();
403+
}
404+
}
405+
373406
@Test
374407
void nullInputsShouldCoerceAsNullValues() throws IOException {
375408
try (InputStream is = new ByteArrayInputStream(new byte[0]);

0 commit comments

Comments
 (0)