This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch 1.X
in repository https://gitbox.apache.org/repos/asf/commons-beanutils.git
The following commit(s) were added to refs/heads/1.X by this push:
new 65b6f8ab Preserve magnitude in BigInteger and BigDecimal locale
converters (#403)
65b6f8ab is described below
commit 65b6f8abcf048944a51bf4149feb7d183c73a548
Author: Dexter.k <[email protected]>
AuthorDate: Mon Jun 22 13:39:39 2026 +0000
Preserve magnitude in BigInteger and BigDecimal locale converters (#403)
DecimalLocaleConverter.parse builds a DecimalFormat without enabling
setParseBigDecimal, so a value past long/double range comes back from
DecimalFormat.parse as a clamped Long or a lossy Double; the BigInteger
and BigDecimal converters then derive their result from that Number and
return it silently wrong (9999999999999999999 -> 9223372036854775807 for
BigInteger, -> 1.0E+19 for BigDecimal).
Add a protected isParseBigDecimal() hook (default false) and pass it to
formatter.setParseBigDecimal; only BigIntegerLocaleConverter and
BigDecimalLocaleConverter override it to true, so DecimalFormat returns a
lossless BigDecimal for them while the narrowing Byte/Short/Integer/Long/
Float/Double converters stay on the Long/Double path.
BigIntegerLocaleConverter
converts the BigDecimal via toBigInteger().
Found by comparing the locale converters with the non-locale
BigInteger/BigDecimal converters that parse the string directly.
---
.../locale/converters/BigDecimalLocaleConverter.java | 5 +++++
.../locale/converters/BigIntegerLocaleConverter.java | 9 +++++++++
.../beanutils/locale/converters/DecimalLocaleConverter.java | 13 +++++++++++++
.../locale/converters/BigDecimalLocaleConverterTest.java | 8 ++++++++
.../locale/converters/BigIntegerLocaleConverterTest.java | 9 +++++++++
5 files changed, 44 insertions(+)
diff --git
a/src/main/java/org/apache/commons/beanutils/locale/converters/BigDecimalLocaleConverter.java
b/src/main/java/org/apache/commons/beanutils/locale/converters/BigDecimalLocaleConverter.java
index 6040c2d0..c9dbb408 100644
---
a/src/main/java/org/apache/commons/beanutils/locale/converters/BigDecimalLocaleConverter.java
+++
b/src/main/java/org/apache/commons/beanutils/locale/converters/BigDecimalLocaleConverter.java
@@ -182,4 +182,9 @@ public class BigDecimalLocaleConverter extends
DecimalLocaleConverter {
throw new ConversionException("Suplied number is not of type
BigDecimal: " + result);
}
}
+
+ @Override
+ protected boolean isParseBigDecimal() {
+ return true;
+ }
}
diff --git
a/src/main/java/org/apache/commons/beanutils/locale/converters/BigIntegerLocaleConverter.java
b/src/main/java/org/apache/commons/beanutils/locale/converters/BigIntegerLocaleConverter.java
index 70bb6239..13bf58b4 100644
---
a/src/main/java/org/apache/commons/beanutils/locale/converters/BigIntegerLocaleConverter.java
+++
b/src/main/java/org/apache/commons/beanutils/locale/converters/BigIntegerLocaleConverter.java
@@ -17,6 +17,7 @@
package org.apache.commons.beanutils.locale.converters;
+import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.ParseException;
import java.util.Locale;
@@ -176,6 +177,9 @@ public class BigIntegerLocaleConverter extends
DecimalLocaleConverter {
if (result == null || result instanceof BigInteger) {
return result;
}
+ if (result instanceof BigDecimal) {
+ return ((BigDecimal) result).toBigInteger();
+ }
if (result instanceof Number) {
return BigInteger.valueOf(((Number) result).longValue());
}
@@ -185,4 +189,9 @@ public class BigIntegerLocaleConverter extends
DecimalLocaleConverter {
throw new ConversionException("Suplied number is not of type
BigInteger: " + result);
}
}
+
+ @Override
+ protected boolean isParseBigDecimal() {
+ return true;
+ }
}
diff --git
a/src/main/java/org/apache/commons/beanutils/locale/converters/DecimalLocaleConverter.java
b/src/main/java/org/apache/commons/beanutils/locale/converters/DecimalLocaleConverter.java
index e3512349..acf9af72 100644
---
a/src/main/java/org/apache/commons/beanutils/locale/converters/DecimalLocaleConverter.java
+++
b/src/main/java/org/apache/commons/beanutils/locale/converters/DecimalLocaleConverter.java
@@ -178,6 +178,18 @@ public class DecimalLocaleConverter extends
BaseLocaleConverter {
* @throws org.apache.commons.beanutils.ConversionException if conversion
cannot be performed successfully.
* @throws ParseException if an error
occurs parsing a String to a Number.
*/
+ /**
+ * Tests whether the underlying {@link DecimalFormat} should parse into a
{@link java.math.BigDecimal} so that magnitude and precision are preserved.
+ * Subclasses that build {@link java.math.BigInteger} or {@link
java.math.BigDecimal} values override this to return {@code true}; the
narrowing converters
+ * keep the default {@code Long} / {@code Double} result.
+ *
+ * @return {@code true} to parse into a {@link java.math.BigDecimal},
{@code false} otherwise.
+ * @since 1.11.1
+ */
+ protected boolean isParseBigDecimal() {
+ return false;
+ }
+
@Override
protected Object parse(final Object value, final String pattern) throws
ParseException {
if (value instanceof Number) {
@@ -188,6 +200,7 @@ public class DecimalLocaleConverter extends
BaseLocaleConverter {
// representation, each call to getInstance actually returns a new
// object.
final DecimalFormat formatter = (DecimalFormat)
NumberFormat.getInstance(locale);
+ formatter.setParseBigDecimal(isParseBigDecimal());
// if some constructors default pattern to null, it makes only sense
// to handle null pattern gracefully
if (pattern != null) {
diff --git
a/src/test/java/org/apache/commons/beanutils/locale/converters/BigDecimalLocaleConverterTest.java
b/src/test/java/org/apache/commons/beanutils/locale/converters/BigDecimalLocaleConverterTest.java
index 4cac72ed..646d4973 100644
---
a/src/test/java/org/apache/commons/beanutils/locale/converters/BigDecimalLocaleConverterTest.java
+++
b/src/test/java/org/apache/commons/beanutils/locale/converters/BigDecimalLocaleConverterTest.java
@@ -228,5 +228,13 @@ public class BigDecimalLocaleConverterTest extends
BaseLocaleConverterTest {
}
+ /**
+ * Test that a value beyond {@code double} precision is preserved instead
of being rounded to a lossy {@code 1.0E+19}.
+ */
+ public void testConvertLargeValueKeepsPrecision() {
+ converter = new BigDecimalLocaleConverter();
+ convertValueNoPattern(converter, "9999999999999999999", new
BigDecimal("9999999999999999999"));
+ }
+
}
diff --git
a/src/test/java/org/apache/commons/beanutils/locale/converters/BigIntegerLocaleConverterTest.java
b/src/test/java/org/apache/commons/beanutils/locale/converters/BigIntegerLocaleConverterTest.java
index acf3ece1..909ffcb5 100644
---
a/src/test/java/org/apache/commons/beanutils/locale/converters/BigIntegerLocaleConverterTest.java
+++
b/src/test/java/org/apache/commons/beanutils/locale/converters/BigIntegerLocaleConverterTest.java
@@ -229,6 +229,15 @@ public class BigIntegerLocaleConverterTest extends
BaseLocaleConverterTest {
}
+ /**
+ * Test that a value beyond {@code long} range keeps its full magnitude
instead of being clamped to {@code Long.MAX_VALUE}.
+ */
+ public void testConvertLargeValueKeepsMagnitude() {
+ converter = new BigIntegerLocaleConverter();
+ convertValueNoPattern(converter, "9999999999999999999", new
BigInteger("9999999999999999999"));
+ convertValueNoPattern(converter, "123456789012345678901234567890", new
BigInteger("123456789012345678901234567890"));
+ }
+
/**
* Tries to convert to an unsupported type. This tests behavior of the base
* class. All locale converters should react in the same way.