diff --git a/release-notes/CREDITS b/release-notes/CREDITS index b82698b5b3..63f21d43bc 100644 --- a/release-notes/CREDITS +++ b/release-notes/CREDITS @@ -93,3 +93,7 @@ Tanguy Leroux (tlrx@github) Mikael Staldal (mikaelstaldal@github) * Contributed fix for #265: `JsonStringEncoder` should allow passing `CharSequence` (2.8.0) + +Kevin Gallardo (newkek@github) + * Reported #296: JsonParserSequence skips a token on a switched Parser + (2.8.0) diff --git a/release-notes/VERSION b/release-notes/VERSION index c26ded7da6..45162a264e 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -39,6 +39,8 @@ JSON library. #290: Add `JsonGenerator.canWriteFormattedNumbers()` for introspection #294: Add `JsonGenerator.writeFieldId(long)` method to support binary formats with non-String keys +#296: JsonParserSequence skips a token on a switched Parser + (reported by Kevin G) - Add `JsonParser.currentToken()` and `JsonParser.currentTokenId()` as replacements for `getCurrentToken()` and `getCurrentTokenId()`, respectively. Existing methods will likely be deprecated in 2.9. diff --git a/src/main/java/com/fasterxml/jackson/core/JsonGenerator.java b/src/main/java/com/fasterxml/jackson/core/JsonGenerator.java index 0048bda7c3..5917f5d9c6 100644 --- a/src/main/java/com/fasterxml/jackson/core/JsonGenerator.java +++ b/src/main/java/com/fasterxml/jackson/core/JsonGenerator.java @@ -1681,7 +1681,7 @@ public void writeOmittedField(String fieldName) throws IOException { } */ public void copyCurrentEvent(JsonParser p) throws IOException { - JsonToken t = p.getCurrentToken(); + JsonToken t = p.currentToken(); // sanity check; what to do? if (t == null) { _reportError("No current event to copy"); @@ -1784,7 +1784,7 @@ public void copyCurrentEvent(JsonParser p) throws IOException */ public void copyCurrentStructure(JsonParser p) throws IOException { - JsonToken t = p.getCurrentToken(); + JsonToken t = p.currentToken(); if (t == null) { _reportError("No current event to copy"); } diff --git a/src/main/java/com/fasterxml/jackson/core/JsonParser.java b/src/main/java/com/fasterxml/jackson/core/JsonParser.java index bd30ae513c..90aed56f84 100644 --- a/src/main/java/com/fasterxml/jackson/core/JsonParser.java +++ b/src/main/java/com/fasterxml/jackson/core/JsonParser.java @@ -884,7 +884,7 @@ public int currentTokenId() { /** * Method that is functionally equivalent to: * - * return getCurrentTokenId() == id + * return currentTokenId() == id * * but may be more efficiently implemented. *

@@ -899,7 +899,7 @@ public int currentTokenId() { /** * Method that is functionally equivalent to: * - * return getCurrentTokenId() == id + * return currentToken() == t * * but may be more efficiently implemented. *

@@ -956,7 +956,7 @@ public int currentTokenId() { *

* Default implementation is equivalent to: *

-     *   getCurrentToken() == JsonToken.START_ARRAY
+     *   currentToken() == JsonToken.START_ARRAY
      *
* but may be overridden by custom parser implementations. * @@ -964,15 +964,15 @@ public int currentTokenId() { * start-array marker (such {@link JsonToken#START_ARRAY}); * false if not. */ - public boolean isExpectedStartArrayToken() { return getCurrentToken() == JsonToken.START_ARRAY; } + public boolean isExpectedStartArrayToken() { return currentToken() == JsonToken.START_ARRAY; } /** * Similar to {@link #isExpectedStartArrayToken()}, but checks whether stream * currently points to {@link JsonToken#START_OBJECT}. - * + * * @since 2.5 */ - public boolean isExpectedStartObjectToken() { return getCurrentToken() == JsonToken.START_OBJECT; } + public boolean isExpectedStartObjectToken() { return currentToken() == JsonToken.START_OBJECT; } /* /********************************************************** @@ -1285,12 +1285,12 @@ public short getShortValue() throws IOException * may be thrown to indicate numeric overflow/underflow. */ public boolean getBooleanValue() throws IOException { - JsonToken t = getCurrentToken(); + JsonToken t = currentToken(); if (t == JsonToken.VALUE_TRUE) return true; if (t == JsonToken.VALUE_FALSE) return false; throw new JsonParseException(this, - String.format("Current token (%s) not of boolean type", t)) - .withRequestPayload(_requestPayload); + String.format("Current token (%s) not of boolean type", t)) + .withRequestPayload(_requestPayload); } /** diff --git a/src/main/java/com/fasterxml/jackson/core/filter/FilteringParserDelegate.java b/src/main/java/com/fasterxml/jackson/core/filter/FilteringParserDelegate.java index bf68cd773b..2bb0165ce8 100644 --- a/src/main/java/com/fasterxml/jackson/core/filter/FilteringParserDelegate.java +++ b/src/main/java/com/fasterxml/jackson/core/filter/FilteringParserDelegate.java @@ -146,11 +146,16 @@ public int getMatchCount() { */ @Override public JsonToken getCurrentToken() { return _currToken; } + @Override public JsonToken currentToken() { return _currToken; } @Override public final int getCurrentTokenId() { final JsonToken t = _currToken; return (t == null) ? JsonTokenId.ID_NO_TOKEN : t.id(); } + @Override public final int currentTokenId() { + final JsonToken t = _currToken; + return (t == null) ? JsonTokenId.ID_NO_TOKEN : t.id(); + } @Override public boolean hasCurrentToken() { return _currToken != null; } @Override public boolean hasTokenId(int id) { diff --git a/src/main/java/com/fasterxml/jackson/core/util/JsonParserSequence.java b/src/main/java/com/fasterxml/jackson/core/util/JsonParserSequence.java index 1100d616b5..0c9c4eb960 100644 --- a/src/main/java/com/fasterxml/jackson/core/util/JsonParserSequence.java +++ b/src/main/java/com/fasterxml/jackson/core/util/JsonParserSequence.java @@ -25,6 +25,14 @@ public class JsonParserSequence extends JsonParserDelegate * Index of the next parser in {@link #_parsers}. */ protected int _nextParser; + + /** + * Flag used to indicate that `JsonParser.nextToken()` should not be called, + * due to parser already pointing to a token. + * + * @since 2.8 + */ + protected boolean _suppressNextToken; /* ******************************************************* @@ -35,6 +43,7 @@ public class JsonParserSequence extends JsonParserDelegate protected JsonParserSequence(JsonParser[] parsers) { super(parsers[0]); + _suppressNextToken = delegate.hasCurrentToken(); _parsers = parsers; _nextParser = 1; } @@ -94,15 +103,21 @@ public void close() throws IOException { } @Override - public JsonToken nextToken() throws IOException, JsonParseException + public JsonToken nextToken() throws IOException { + if (delegate == null) { + return null; + } + if (_suppressNextToken) { + _suppressNextToken = false; + return delegate.currentToken(); + } JsonToken t = delegate.nextToken(); - if (t != null) return t; - while (switchToNext()) { - t = delegate.nextToken(); - if (t != null) return t; + while ((t == null) && switchToNext()) { + t = delegate.hasCurrentToken() + ? delegate.currentToken() : delegate.nextToken(); } - return null; + return t; } /* diff --git a/src/test/java/com/fasterxml/jackson/core/json/ParserSequenceTest.java b/src/test/java/com/fasterxml/jackson/core/json/ParserSequenceTest.java index 738fa25d86..f555186f99 100644 --- a/src/test/java/com/fasterxml/jackson/core/json/ParserSequenceTest.java +++ b/src/test/java/com/fasterxml/jackson/core/json/ParserSequenceTest.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.util.JsonParserSequence; +@SuppressWarnings("resource") public class ParserSequenceTest extends com.fasterxml.jackson.core.BaseTest { @@ -43,8 +44,22 @@ public void testSimple() throws Exception assertTrue(seq.isClosed()); seq.close(); - // redundant, but call to remove IDE warnings - p1.close(); - p2.close(); + } + + // for [jackson-core#296] + public void testInitialized() throws Exception + { + JsonParser p1 = JSON_FACTORY.createParser("1 2"); + JsonParser p2 = JSON_FACTORY.createParser("3 false"); + // consume '1', move to '2' + assertToken(JsonToken.VALUE_NUMBER_INT, p1.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, p1.nextToken()); + + JsonParserSequence seq = JsonParserSequence.createFlattened(p1, p2); + assertToken(JsonToken.VALUE_NUMBER_INT, seq.nextToken()); + assertEquals(2, seq.getIntValue()); + assertToken(JsonToken.VALUE_NUMBER_INT, seq.nextToken()); + assertEquals(3, seq.getIntValue()); + seq.close(); } } diff --git a/src/test/java/com/fasterxml/jackson/core/json/StringGenerationTest.java b/src/test/java/com/fasterxml/jackson/core/json/StringGenerationTest.java index 86d991fad1..4fd67c1956 100644 --- a/src/test/java/com/fasterxml/jackson/core/json/StringGenerationTest.java +++ b/src/test/java/com/fasterxml/jackson/core/json/StringGenerationTest.java @@ -287,7 +287,7 @@ private void _testLongerRandomMulti(int readMode, String text, boolean charArray } offset += act.length(); } - assertEquals(JsonToken.END_ARRAY, p.getCurrentToken()); + assertEquals(JsonToken.END_ARRAY, p.currentToken()); p.close(); } } diff --git a/src/test/java/com/fasterxml/jackson/core/json/TestParserOverrides.java b/src/test/java/com/fasterxml/jackson/core/json/TestParserOverrides.java index d382428acf..244effd753 100644 --- a/src/test/java/com/fasterxml/jackson/core/json/TestParserOverrides.java +++ b/src/test/java/com/fasterxml/jackson/core/json/TestParserOverrides.java @@ -45,14 +45,14 @@ public void _testTokenAccess(JsonFactory jf, boolean useStream) throws Exception JsonParser jp = useStream ? jf.createParser(new ByteArrayInputStream(DOC.getBytes("UTF-8"))) : jf.createParser(DOC); - assertNull(jp.getCurrentToken()); + assertNull(jp.currentToken()); jp.clearCurrentToken(); - assertNull(jp.getCurrentToken()); + assertNull(jp.currentToken()); assertNull(jp.getEmbeddedObject()); assertToken(JsonToken.START_ARRAY, jp.nextToken()); - assertToken(JsonToken.START_ARRAY, jp.getCurrentToken()); + assertToken(JsonToken.START_ARRAY, jp.currentToken()); jp.clearCurrentToken(); - assertNull(jp.getCurrentToken()); + assertNull(jp.currentToken()); // Also: no codec defined by default try { jp.readValueAsTree(); @@ -69,7 +69,7 @@ private void _testCurrentName(JsonFactory jf, boolean useStream) throws Exceptio JsonParser jp = useStream ? jf.createParser(new ByteArrayInputStream(DOC.getBytes("UTF-8"))) : jf.createParser(new StringReader(DOC)); - assertNull(jp.getCurrentToken()); + assertNull(jp.currentToken()); assertToken(JsonToken.START_OBJECT, jp.nextToken()); assertToken(JsonToken.FIELD_NAME, jp.nextToken()); assertEquals("first", jp.getCurrentName()); @@ -94,9 +94,7 @@ private void _testCurrentName(JsonFactory jf, boolean useStream) throws Exceptio assertToken(JsonToken.END_OBJECT, jp.nextToken()); jp.clearCurrentToken(); - assertNull(jp.getCurrentToken()); + assertNull(jp.currentToken()); jp.close(); } - - } diff --git a/src/test/java/com/fasterxml/jackson/core/json/TestRootValues.java b/src/test/java/com/fasterxml/jackson/core/json/TestRootValues.java index 585dbbee48..625d2845ad 100644 --- a/src/test/java/com/fasterxml/jackson/core/json/TestRootValues.java +++ b/src/test/java/com/fasterxml/jackson/core/json/TestRootValues.java @@ -45,7 +45,7 @@ private void _testBrokeanNumber(boolean useStream) throws Exception // Should fail, right away try { p.nextToken(); - fail("Ought to fail! Instead, got token: "+p.getCurrentToken()); + fail("Ought to fail! Instead, got token: "+p.currentToken()); } catch (JsonParseException e) { verifyException(e, "unexpected character"); } diff --git a/src/test/java/com/fasterxml/jackson/core/main/TestGeneratorCopy.java b/src/test/java/com/fasterxml/jackson/core/main/TestGeneratorCopy.java index 853ecb756d..e9e26f2587 100644 --- a/src/test/java/com/fasterxml/jackson/core/main/TestGeneratorCopy.java +++ b/src/test/java/com/fasterxml/jackson/core/main/TestGeneratorCopy.java @@ -26,7 +26,7 @@ public void testCopyRootTokens() while ((t = jp.nextToken()) != null) { gen.copyCurrentEvent(jp); // should not change parser state: - assertToken(t, jp.getCurrentToken()); + assertToken(t, jp.currentToken()); } jp.close(); gen.close(); @@ -46,14 +46,14 @@ public void testCopyArrayTokens() assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); gen.copyCurrentEvent(jp); // should not change parser state: - assertToken(JsonToken.VALUE_NUMBER_INT, jp.getCurrentToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.currentToken()); assertEquals(123, jp.getIntValue()); // And then let's copy the array assertToken(JsonToken.START_ARRAY, jp.nextToken()); gen.copyCurrentStructure(jp); // which will advance parser to matching close Array - assertToken(JsonToken.END_ARRAY, jp.getCurrentToken()); + assertToken(JsonToken.END_ARRAY, jp.currentToken()); jp.close(); gen.close(); @@ -72,7 +72,7 @@ public void testCopyObjectTokens() assertToken(JsonToken.START_OBJECT, jp.nextToken()); gen.copyCurrentStructure(jp); // which will advance parser to matching end Object - assertToken(JsonToken.END_OBJECT, jp.getCurrentToken()); + assertToken(JsonToken.END_OBJECT, jp.currentToken()); jp.close(); gen.close(); diff --git a/src/test/java/com/fasterxml/jackson/core/read/JsonParserTest.java b/src/test/java/com/fasterxml/jackson/core/read/JsonParserTest.java index 498bb9fa7d..55442e1015 100644 --- a/src/test/java/com/fasterxml/jackson/core/read/JsonParserTest.java +++ b/src/test/java/com/fasterxml/jackson/core/read/JsonParserTest.java @@ -226,7 +226,7 @@ private void _testSkipping(int mode) throws Exception // First, skipping of the whole thing assertToken(JsonToken.START_ARRAY, p.nextToken()); p.skipChildren(); - assertEquals(JsonToken.END_ARRAY, p.getCurrentToken()); + assertEquals(JsonToken.END_ARRAY, p.currentToken()); if (!isInputData) { JsonToken t = p.nextToken(); if (t != null) { @@ -242,27 +242,27 @@ private void _testSkipping(int mode) throws Exception assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); p.skipChildren(); // shouldn't move - assertToken(JsonToken.VALUE_NUMBER_INT, p.getCurrentToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.currentToken()); assertEquals(1, p.getIntValue()); assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); // then skip array assertToken(JsonToken.START_ARRAY, p.nextToken()); p.skipChildren(); - assertToken(JsonToken.END_ARRAY, p.getCurrentToken()); + assertToken(JsonToken.END_ARRAY, p.currentToken()); assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); assertToken(JsonToken.START_OBJECT, p.nextToken()); p.skipChildren(); - assertToken(JsonToken.END_OBJECT, p.getCurrentToken()); + assertToken(JsonToken.END_OBJECT, p.currentToken()); assertToken(JsonToken.START_ARRAY, p.nextToken()); p.skipChildren(); - assertToken(JsonToken.END_ARRAY, p.getCurrentToken()); + assertToken(JsonToken.END_ARRAY, p.currentToken()); assertToken(JsonToken.START_OBJECT, p.nextToken()); p.skipChildren(); - assertToken(JsonToken.END_OBJECT, p.getCurrentToken()); + assertToken(JsonToken.END_OBJECT, p.currentToken()); assertToken(JsonToken.END_ARRAY, p.nextToken()); diff --git a/src/test/java/com/fasterxml/jackson/core/util/TestDelegates.java b/src/test/java/com/fasterxml/jackson/core/util/TestDelegates.java index 9cce04ac48..8fe7db3304 100644 --- a/src/test/java/com/fasterxml/jackson/core/util/TestDelegates.java +++ b/src/test/java/com/fasterxml/jackson/core/util/TestDelegates.java @@ -18,7 +18,7 @@ public void testParserDelegate() throws IOException JsonParser parser = JSON_F.createParser("[ 1, true, null, { } ]"); JsonParserDelegate del = new JsonParserDelegate(parser); - assertNull(del.getCurrentToken()); + assertNull(del.currentToken()); assertToken(JsonToken.START_ARRAY, del.nextToken()); assertEquals("[", del.getText()); assertToken(JsonToken.VALUE_NUMBER_INT, del.nextToken());