From 028cfcb5518234cf47c510b96097f3c316ba03c6 Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 13 Sep 2024 21:47:22 +0100 Subject: [PATCH 1/3] add extra writeNumber method --- .../jackson/databind/util/TokenBuffer.java | 27 ++++++++-- .../databind/util/TokenBufferTest.java | 51 +++++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java b/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java index c5a0590c30..d11c251c96 100644 --- a/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java +++ b/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java @@ -954,6 +954,27 @@ public void writeNumber(String encodedValue) throws IOException { _appendValue(JsonToken.VALUE_NUMBER_FLOAT, encodedValue); } + /** + * Write method that can be used for custom numeric types that can + * not be (easily?) converted to "standard" Java number types. + * Because numbers are not surrounded by double quotes, regular + * {@link #writeString} method can not be used; nor + * {@link #writeRaw} because that does not properly handle + * value separators needed in Array or Object contexts. + * + * @param encodedValue Textual (possibly format) number representation to write + * @param isInteger Whether value should be considered an integer + * + * @throws IOException if there is either an underlying I/O problem or encoding + * issue at format layer + * @since 2.18 + */ + public void writeNumber(String encodedValue, boolean isInteger) throws IOException { + _appendValue( + isInteger ? JsonToken.VALUE_NUMBER_INT : JsonToken.VALUE_NUMBER_FLOAT, + encodedValue); + } + private void writeLazyInteger(Object encodedValue) throws IOException { _appendValue(JsonToken.VALUE_NUMBER_INT, encodedValue); } @@ -1853,8 +1874,7 @@ public float getFloatValue() throws IOException { @Override public int getIntValue() throws IOException { - Number n = (_currToken == JsonToken.VALUE_NUMBER_INT) ? - ((Number) _currentObject()) : getNumberValue(); + final Number n = getNumberValue(false); if ((n instanceof Integer) || _smallerThanInt(n)) { return n.intValue(); } @@ -1863,8 +1883,7 @@ public int getIntValue() throws IOException @Override public long getLongValue() throws IOException { - Number n = (_currToken == JsonToken.VALUE_NUMBER_INT) ? - ((Number) _currentObject()) : getNumberValue(); + final Number n = getNumberValue(false); if ((n instanceof Long) || _smallerThanLong(n)) { return n.longValue(); } diff --git a/src/test/java/com/fasterxml/jackson/databind/util/TokenBufferTest.java b/src/test/java/com/fasterxml/jackson/databind/util/TokenBufferTest.java index 6bc0689ba1..8be86ecc58 100644 --- a/src/test/java/com/fasterxml/jackson/databind/util/TokenBufferTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/util/TokenBufferTest.java @@ -236,6 +236,57 @@ public void testNumberOverflowLong() throws IOException } } + @Test + public void testNumberIntAsString() throws IOException + { + try (TokenBuffer buf = new TokenBuffer(null, false)) { + buf.writeNumber("123", true); + try (JsonParser p = buf.asParser()) { + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(NumberType.BIG_INTEGER, p.getNumberType()); + assertEquals(123, p.getIntValue()); + } + } + try (TokenBuffer buf = new TokenBuffer(null, false)) { + buf.writeNumber("-123", true); + try (JsonParser p = buf.asParser()) { + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(NumberType.BIG_INTEGER, p.getNumberType()); + assertEquals(-123L, p.getLongValue()); + } + } + try (TokenBuffer buf = new TokenBuffer(null, false)) { + buf.writeNumber("123", false); + try (JsonParser p = buf.asParser()) { + assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); + assertEquals(NumberType.BIG_DECIMAL, p.getNumberType()); + assertEquals(123.0, p.getFloatValue()); + } + } + // legacy method assumes Decimal type + try (TokenBuffer buf = new TokenBuffer(null, false)) { + buf.writeNumber("123"); + try (JsonParser p = buf.asParser()) { + assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); + assertEquals(NumberType.BIG_DECIMAL, p.getNumberType()); + assertEquals(123.0, p.getFloatValue()); + } + } + } + + @Test + public void testNumberNonIntAsStringNoCoerce() throws IOException + { + try (TokenBuffer buf = new TokenBuffer(null, false)) { + buf.writeNumber("1234.567", true); + try (JsonParser p = buf.asParser()) { + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(NumberType.BIG_INTEGER, p.getNumberType()); + assertThrows(NumberFormatException.class, p::getIntValue); + } + } + } + @Test public void testBigIntAsString() throws IOException { From 5909f78b97182d37c210dfa7a5ca692a96aae17c Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Fri, 13 Sep 2024 21:54:50 +0100 Subject: [PATCH 2/3] Update TokenBuffer.java --- .../java/com/fasterxml/jackson/databind/util/TokenBuffer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java b/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java index d11c251c96..2ccb0b6d71 100644 --- a/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java +++ b/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java @@ -962,7 +962,7 @@ public void writeNumber(String encodedValue) throws IOException { * {@link #writeRaw} because that does not properly handle * value separators needed in Array or Object contexts. * - * @param encodedValue Textual (possibly format) number representation to write + * @param encodedValue Textual (possibly formatted) number representation to write * @param isInteger Whether value should be considered an integer * * @throws IOException if there is either an underlying I/O problem or encoding From 201a873ae3edf229940765176524154c6270b0b7 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 13 Sep 2024 16:23:32 -0700 Subject: [PATCH 3/3] Add release notes --- release-notes/VERSION-2.x | 2 ++ 1 file changed, 2 insertions(+) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index d0f8b793f8..fece6f0582 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -77,6 +77,8 @@ Project: jackson-databind (contributed by Carter K) #4694: Deserializing `BigDecimal` with large number of decimals result in incorrect value (reported by @lnthai2002) +#4699: Add extra `writeNumber()` method in `TokenBuffer` + (contributed by @pjfanning) 2.17.2 (05-Jul-2024)