Skip to content

Iterating over an array stream from an object field which has been mapped throws an IllegalStateException #17

@tomwhoiscontrary

Description

@tomwhoiscontrary

Say you have some JSON which defines an object, and inside that object there is an array. You parse to the start of the array, then call JsonParser#getArrayStream, then call Stream#map on that to transform it somehow, then call Stream#iterator on the result, and iterate over the iterator.

I think this should result in iterating over the transformed elements of the array.

However, it throws an IllegalStateException from the hasNext call at the end of the iteration.

This code (the body of a JUnit 5 test):

        try (JsonParser parser = Json.createParser(new StringReader("{\"numbers\": [1, 2, 3]}"))) {
            assertThat(parser.next(), equalTo(JsonParser.Event.START_OBJECT));
            assertThat(parser.next(), equalTo(JsonParser.Event.KEY_NAME));
            assertThat(parser.getString(), equalTo("numbers"));
            assertThat(parser.next(), equalTo(JsonParser.Event.START_ARRAY));

            Stream<JsonValue> numbersStream = parser.getArrayStream().map(Function.identity());
            Iterator<JsonValue> numbersIterator = numbersStream.iterator();

            List<Integer> numbersList = new ArrayList<>();
            while (numbersIterator.hasNext()) {
                numbersList.add(((JsonNumber) numbersIterator.next()).intValue());
            }

            assertThat(numbersList, equalTo(List.of(1, 2, 3)));
        }

Throws this exception:

java.lang.IllegalStateException: getValue() was called in illegal parser event END_OBJECT.
	at org.leadpony.joy.core.AbstractJsonParser.newIllegalStateException(AbstractJsonParser.java:234)
	at org.leadpony.joy.core.AbstractJsonParser.getValue(AbstractJsonParser.java:87)
	at org.leadpony.joy.core.JsonStreams$1.tryAdvance(JsonStreams.java:46)
	at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.lambda$initPartialTraversalState$0(StreamSpliterators.java:292)
	at java.base/java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.fillBuffer(StreamSpliterators.java:206)
	at java.base/java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.doAdvance(StreamSpliterators.java:169)
	at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.tryAdvance(StreamSpliterators.java:298)
	at java.base/java.util.Spliterators$1Adapter.hasNext(Spliterators.java:681)

Using Joy 2.1.0 on OpenJDK 17+35.

Note that the Stream#map call takes Function.identity() as a parameter. If you remove the map call, this code is semantically the same, but now it works - it doesn't throw an exception, and the test passes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions