Skip to content

Commit 579784d

Browse files
committed
correct error in converting doubles to big decimals
1 parent c03054b commit 579784d

2 files changed

Lines changed: 24 additions & 4 deletions

File tree

src/main/java/org/json/JSONObject.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,18 @@ public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) {
11591159
* to convert.
11601160
*/
11611161
static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue) {
1162+
return objectToBigDecimal(val, defaultValue, true);
1163+
}
1164+
1165+
/**
1166+
* @param val value to convert
1167+
* @param defaultValue default value to return is the conversion doesn't work or is null.
1168+
* @param exact When <code>true</code>, then {@link Double} and {@link Float} values will be converted exactly.
1169+
* When <code>false</code>, they will be converted to {@link String} values before converting to {@link BigDecimal}.
1170+
* @return BigDecimal conversion of the original value, or the defaultValue if unable
1171+
* to convert.
1172+
*/
1173+
static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue, boolean exact) {
11621174
if (NULL.equals(val)) {
11631175
return defaultValue;
11641176
}
@@ -1172,7 +1184,14 @@ static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue) {
11721184
if (!numberIsFinite((Number)val)) {
11731185
return defaultValue;
11741186
}
1175-
return new BigDecimal(((Number) val).doubleValue());
1187+
if (exact) {
1188+
return new BigDecimal(((Number)val).doubleValue());
1189+
}else {
1190+
// use the string constructor so that we maintain "nice" values for doubles and floats
1191+
// the double constructor will translate doubles to "exact" values instead of the likely
1192+
// intended representation
1193+
return new BigDecimal(val.toString());
1194+
}
11761195
}
11771196
if (val instanceof Long || val instanceof Integer
11781197
|| val instanceof Short || val instanceof Byte){
@@ -2132,8 +2151,8 @@ static boolean isNumberSimilar(Number l, Number r) {
21322151
// BigDecimal should be able to handle all of our number types that we support through
21332152
// documentation. Convert to BigDecimal first, then use the Compare method to
21342153
// decide equality.
2135-
final BigDecimal lBigDecimal = objectToBigDecimal(l, null);
2136-
final BigDecimal rBigDecimal = objectToBigDecimal(r, null);
2154+
final BigDecimal lBigDecimal = objectToBigDecimal(l, null, false);
2155+
final BigDecimal rBigDecimal = objectToBigDecimal(r, null, false);
21372156
if (lBigDecimal == null || rBigDecimal == null) {
21382157
return false;
21392158
}

src/test/java/org/json/junit/JSONObjectTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ public void verifySimilar() {
126126

127127
assertTrue("Should eval to true", obj1.similar(obj4));
128128

129+
// verify that a double and big decimal are "similar"
129130
assertTrue("should eval to true",new JSONObject().put("a",1.1d).similar(new JSONObject("{\"a\":1.1}")));
130131

131132
}
@@ -942,7 +943,7 @@ public void stringToValueNumbersTest() {
942943
assertTrue("-0 Should be a Double!",JSONObject.stringToValue("-0") instanceof Double);
943944
assertTrue("-0.0 Should be a Double!",JSONObject.stringToValue("-0.0") instanceof Double);
944945
assertTrue("'-' Should be a String!",JSONObject.stringToValue("-") instanceof String);
945-
assertTrue( "0.2 should be a Double!",
946+
assertTrue( "0.2 should be a BigDecimal!",
946947
JSONObject.stringToValue( "0.2" ) instanceof BigDecimal );
947948
assertTrue( "Doubles should be BigDecimal, even when incorrectly converting floats!",
948949
JSONObject.stringToValue( new Double( "0.2f" ).toString() ) instanceof BigDecimal );

0 commit comments

Comments
 (0)