Skip to content

Commit ef871bb

Browse files
authored
Add extra writeNumber() method in TokenBuffer (#4699)
1 parent 7c336bf commit ef871bb

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

release-notes/VERSION-2.x

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ Project: jackson-databind
7777
(contributed by Carter K)
7878
#4694: Deserializing `BigDecimal` with large number of decimals result in incorrect value
7979
(reported by @lnthai2002)
80+
#4699: Add extra `writeNumber()` method in `TokenBuffer`
81+
(contributed by @pjfanning)
8082
8183
2.17.2 (05-Jul-2024)
8284

src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,27 @@ public void writeNumber(String encodedValue) throws IOException {
954954
_appendValue(JsonToken.VALUE_NUMBER_FLOAT, encodedValue);
955955
}
956956

957+
/**
958+
* Write method that can be used for custom numeric types that can
959+
* not be (easily?) converted to "standard" Java number types.
960+
* Because numbers are not surrounded by double quotes, regular
961+
* {@link #writeString} method can not be used; nor
962+
* {@link #writeRaw} because that does not properly handle
963+
* value separators needed in Array or Object contexts.
964+
*
965+
* @param encodedValue Textual (possibly formatted) number representation to write
966+
* @param isInteger Whether value should be considered an integer
967+
*
968+
* @throws IOException if there is either an underlying I/O problem or encoding
969+
* issue at format layer
970+
* @since 2.18
971+
*/
972+
public void writeNumber(String encodedValue, boolean isInteger) throws IOException {
973+
_appendValue(
974+
isInteger ? JsonToken.VALUE_NUMBER_INT : JsonToken.VALUE_NUMBER_FLOAT,
975+
encodedValue);
976+
}
977+
957978
private void writeLazyInteger(Object encodedValue) throws IOException {
958979
_appendValue(JsonToken.VALUE_NUMBER_INT, encodedValue);
959980
}
@@ -1853,8 +1874,7 @@ public float getFloatValue() throws IOException {
18531874
@Override
18541875
public int getIntValue() throws IOException
18551876
{
1856-
Number n = (_currToken == JsonToken.VALUE_NUMBER_INT) ?
1857-
((Number) _currentObject()) : getNumberValue();
1877+
final Number n = getNumberValue(false);
18581878
if ((n instanceof Integer) || _smallerThanInt(n)) {
18591879
return n.intValue();
18601880
}
@@ -1863,8 +1883,7 @@ public int getIntValue() throws IOException
18631883

18641884
@Override
18651885
public long getLongValue() throws IOException {
1866-
Number n = (_currToken == JsonToken.VALUE_NUMBER_INT) ?
1867-
((Number) _currentObject()) : getNumberValue();
1886+
final Number n = getNumberValue(false);
18681887
if ((n instanceof Long) || _smallerThanLong(n)) {
18691888
return n.longValue();
18701889
}

src/test/java/com/fasterxml/jackson/databind/util/TokenBufferTest.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,57 @@ public void testNumberOverflowLong() throws IOException
236236
}
237237
}
238238

239+
@Test
240+
public void testNumberIntAsString() throws IOException
241+
{
242+
try (TokenBuffer buf = new TokenBuffer(null, false)) {
243+
buf.writeNumber("123", true);
244+
try (JsonParser p = buf.asParser()) {
245+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
246+
assertEquals(NumberType.BIG_INTEGER, p.getNumberType());
247+
assertEquals(123, p.getIntValue());
248+
}
249+
}
250+
try (TokenBuffer buf = new TokenBuffer(null, false)) {
251+
buf.writeNumber("-123", true);
252+
try (JsonParser p = buf.asParser()) {
253+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
254+
assertEquals(NumberType.BIG_INTEGER, p.getNumberType());
255+
assertEquals(-123L, p.getLongValue());
256+
}
257+
}
258+
try (TokenBuffer buf = new TokenBuffer(null, false)) {
259+
buf.writeNumber("123", false);
260+
try (JsonParser p = buf.asParser()) {
261+
assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
262+
assertEquals(NumberType.BIG_DECIMAL, p.getNumberType());
263+
assertEquals(123.0, p.getFloatValue());
264+
}
265+
}
266+
// legacy method assumes Decimal type
267+
try (TokenBuffer buf = new TokenBuffer(null, false)) {
268+
buf.writeNumber("123");
269+
try (JsonParser p = buf.asParser()) {
270+
assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
271+
assertEquals(NumberType.BIG_DECIMAL, p.getNumberType());
272+
assertEquals(123.0, p.getFloatValue());
273+
}
274+
}
275+
}
276+
277+
@Test
278+
public void testNumberNonIntAsStringNoCoerce() throws IOException
279+
{
280+
try (TokenBuffer buf = new TokenBuffer(null, false)) {
281+
buf.writeNumber("1234.567", true);
282+
try (JsonParser p = buf.asParser()) {
283+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
284+
assertEquals(NumberType.BIG_INTEGER, p.getNumberType());
285+
assertThrows(NumberFormatException.class, p::getIntValue);
286+
}
287+
}
288+
}
289+
239290
@Test
240291
public void testBigIntAsString() throws IOException
241292
{

0 commit comments

Comments
 (0)