Skip to content

Commit fa8f901

Browse files
committed
Use BigDecimal.compareTo instead of string comparison in packBigDecimal
Replace the string-based lossy check with `decimal.compareTo(BigDecimal.valueOf(doubleValue)) != 0`, avoiding two stripTrailingZeros + toEngineeringString allocations per BigDecimal write.
1 parent ec29bb0 commit fa8f901

2 files changed

Lines changed: 24 additions & 2 deletions

File tree

msgpack-jackson3/src/main/java/org/msgpack/jackson/dataformat/MessagePackGenerator.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,8 +433,7 @@ private void packBigDecimal(BigDecimal decimal)
433433

434434
if (failedToPackAsBI) {
435435
double doubleValue = decimal.doubleValue();
436-
if (!decimal.stripTrailingZeros().toEngineeringString().equals(
437-
BigDecimal.valueOf(doubleValue).stripTrailingZeros().toEngineeringString())) {
436+
if (decimal.compareTo(BigDecimal.valueOf(doubleValue)) != 0) {
438437
throw new IllegalArgumentException("MessagePack cannot serialize a BigDecimal that can't be represented as double. " + decimal);
439438
}
440439
messagePacker.packDouble(doubleValue);

msgpack-jackson3/src/test/java/org/msgpack/jackson/dataformat/MessagePackGeneratorTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,29 @@ public void testBigDecimal()
351351
}
352352
}
353353

354+
@Test
355+
public void testBigDecimalCompareTo()
356+
throws IOException
357+
{
358+
ObjectMapper mapper = new MessagePackMapper(new MessagePackFactory());
359+
360+
// BigDecimal with trailing zeros is representable as double — must not throw
361+
BigDecimal trailingZeros = new BigDecimal("1.50");
362+
byte[] bytes = mapper.writeValueAsBytes(trailingZeros);
363+
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(bytes);
364+
assertEquals(1.5, unpacker.unpackDouble(), 0.0);
365+
366+
// BigDecimal with precision beyond double range must throw
367+
BigDecimal tooHighPrecision = new BigDecimal("1.00000000000000000000000000000000000001");
368+
try {
369+
mapper.writeValueAsBytes(tooHighPrecision);
370+
assertTrue(false);
371+
}
372+
catch (IllegalArgumentException e) {
373+
assertTrue(true);
374+
}
375+
}
376+
354377
@Test
355378
public void testEnableFeatureAutoCloseTarget()
356379
throws IOException

0 commit comments

Comments
 (0)