Skip to content

Add extra writeNumber() method in TokenBuffer #4699

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
27 changes: 23 additions & 4 deletions src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 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
* 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);
}
Expand Down Expand Up @@ -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();
}
Expand All @@ -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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down