diff --git a/src/main/java/com/fasterxml/jackson/core/JsonParser.java b/src/main/java/com/fasterxml/jackson/core/JsonParser.java index 15c1273ade..c4955a3d11 100644 --- a/src/main/java/com/fasterxml/jackson/core/JsonParser.java +++ b/src/main/java/com/fasterxml/jackson/core/JsonParser.java @@ -170,7 +170,13 @@ public enum Feature { */ @Deprecated ALLOW_NUMERIC_LEADING_ZEROS(false), - + + /** + * @deprecated Use {@link com.fasterxml.jackson.core.json.JsonReadFeature#ALLOW_LEADING_DECIMAL_POINT_FOR_NUMBERS} instead + */ + @Deprecated + ALLOW_LEADING_DECIMAL_POINT_FOR_NUMBERS(false), + /** * Feature that allows parser to recognize set of * "Not-a-Number" (NaN) tokens as legal floating number diff --git a/src/main/java/com/fasterxml/jackson/core/json/JsonReadFeature.java b/src/main/java/com/fasterxml/jackson/core/json/JsonReadFeature.java index 11022796b4..82ad94ab99 100644 --- a/src/main/java/com/fasterxml/jackson/core/json/JsonReadFeature.java +++ b/src/main/java/com/fasterxml/jackson/core/json/JsonReadFeature.java @@ -118,7 +118,8 @@ public enum JsonReadFeature * * @since 2.11 */ - ALLOW_LEADING_DECIMAL_POINT_FOR_NUMBERS(false, null), + @SuppressWarnings("deprecation") + ALLOW_LEADING_DECIMAL_POINT_FOR_NUMBERS(false, JsonParser.Feature.ALLOW_LEADING_DECIMAL_POINT_FOR_NUMBERS), /** * Feature that allows parser to recognize set of diff --git a/src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java b/src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java index 48425a7809..22ddcd0836 100644 --- a/src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java +++ b/src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java @@ -670,6 +670,7 @@ public JsonToken nextToken() throws IOException case '7': case '8': case '9': + case '.': // as per [core#611] t = _parsePosNumber(i); break; case 'f': @@ -735,6 +736,7 @@ private final JsonToken _nextTokenNotInObject(int i) throws IOException case '7': case '8': case '9': + case '.': // as per [core#611] return (_currToken = _parsePosNumber(i)); } return (_currToken = _handleUnexpectedValue(i)); @@ -840,6 +842,7 @@ public String nextFieldName() throws IOException case '7': case '8': case '9': + case '.': // as per [core#611] t = _parsePosNumber(i); break; case 'f': @@ -996,7 +999,8 @@ protected JsonToken _parsePosNumber(int c) throws IOException { char[] outBuf = _textBuffer.emptyAndGetCurrentSegment(); int outPtr; - + final boolean forceFloat; + // One special case: if first char is 0, must not be followed by a digit. // Gets bit tricky as we only want to retain 0 if it's the full value if (c == INT_0) { @@ -1007,7 +1011,16 @@ protected JsonToken _parsePosNumber(int c) throws IOException outBuf[0] = '0'; outPtr = 1; } + forceFloat = false; } else { + forceFloat = (c == INT_PERIOD); + if (forceFloat) { + // [core#611]: allow optionally leading decimal point + if (!isEnabled(JsonReadFeature.ALLOW_LEADING_DECIMAL_POINT_FOR_NUMBERS.mappedFeature())) { + return _handleUnexpectedValue(c); + } + } + outBuf[0] = (char) c; c = _inputData.readUnsignedByte(); outPtr = 1; @@ -1024,7 +1037,7 @@ protected JsonToken _parsePosNumber(int c) throws IOException outBuf[outPtr++] = (char) c; c = _inputData.readUnsignedByte(); } - if (c == '.' || c == 'e' || c == 'E') { + if (c == '.' || c == 'e' || c == 'E' || forceFloat) { return _parseFloat(outBuf, outPtr, c, false, intLen); } _textBuffer.setCurrentLength(outPtr); diff --git a/src/test/java/com/fasterxml/jackson/failing/NonStandardNumbers611Test.java b/src/test/java/com/fasterxml/jackson/failing/NonStandardNumbers611Test.java index ab95dbc06a..c6109b72a5 100644 --- a/src/test/java/com/fasterxml/jackson/failing/NonStandardNumbers611Test.java +++ b/src/test/java/com/fasterxml/jackson/failing/NonStandardNumbers611Test.java @@ -22,31 +22,30 @@ public void testLeadingDotInDecimal() throws Exception { } } - public void testLeadingDotInDecimalAllowed() throws Exception { - final JsonFactory f = JsonFactory.builder() - .enable(JsonReadFeature.ALLOW_LEADING_DECIMAL_POINT_FOR_NUMBERS) - .build(); - -// TODO: -/* - for (int mode : ALL_MODES) { - _testLeadingDotInDecimalAllowed(f, mode); - } - */ + private final JsonFactory JSON_F = JsonFactory.builder() + .enable(JsonReadFeature.ALLOW_LEADING_DECIMAL_POINT_FOR_NUMBERS) + .build(); + + public void testLeadingDotInDecimalAllowedAsync() throws Exception { + _testLeadingDotInDecimalAllowed(JSON_F, MODE_DATA_INPUT); + } + public void testLeadingDotInDecimalAllowedBytes() throws Exception { + _testLeadingDotInDecimalAllowed(JSON_F, MODE_INPUT_STREAM); + _testLeadingDotInDecimalAllowed(JSON_F, MODE_INPUT_STREAM_THROTTLED); + } - _testLeadingDotInDecimalAllowed(f, MODE_INPUT_STREAM); - _testLeadingDotInDecimalAllowed(f, MODE_INPUT_STREAM_THROTTLED); - _testLeadingDotInDecimalAllowed(f, MODE_READER); - _testLeadingDotInDecimalAllowed(f, MODE_DATA_INPUT); + public void testLeadingDotInDecimalAllowedReader() throws Exception { + _testLeadingDotInDecimalAllowed(JSON_F, MODE_READER); } private void _testLeadingDotInDecimalAllowed(JsonFactory f, int mode) throws Exception { - JsonParser p = createParser(f, mode, " .123 "); + JsonParser p = createParser(f, mode, " .125 "); assertEquals(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); - assertEquals(0.123, p.getValueAsDouble()); - assertEquals("0.123", p.getDecimalValue().toString()); + assertEquals(0.125, p.getValueAsDouble()); + assertEquals("0.125", p.getDecimalValue().toString()); + assertEquals(".125", p.getText()); p.close(); } }