Skip to content

Commit d371468

Browse files
ind1godkulp
authored andcommitted
Use BigDecimal instead of Double to avoid loss of precision
1 parent 23a64ee commit d371468

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

src/main/java/org/codehaus/jettison/json/JSONTokener.java

+14-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.codehaus.jettison.json;
1717

18+
import java.math.BigDecimal;
19+
1820
/**
1921
* A JSONTokener takes a source string and extracts characters and tokens from
2022
* it. It is used by the JSONObject and JSONArray constructors to parse
@@ -24,6 +26,11 @@
2426
*/
2527
public class JSONTokener {
2628

29+
private static final String USE_BIGDECIMAL_JSONTOKENER_KEY = "jettison.json.jsontokener.use_bigdecimal";
30+
public static final boolean USE_BIGDECIMAL_JSONTOKENER = Boolean.getBoolean( USE_BIGDECIMAL_JSONTOKENER_KEY );
31+
protected boolean useBigDecimal = USE_BIGDECIMAL_JSONTOKENER;
32+
33+
2734
/**
2835
* The index of the next character.
2936
*/
@@ -308,7 +315,8 @@ public String nextTo(String delimiters) {
308315

309316

310317
/**
311-
* Get the next value. The value can be a Boolean, Double, Integer,
318+
* Get the next value. The value can be a Boolean, Double/BigDecimal
319+
* (depending on -Djettison.json.jsontokener.use_bigdecimal), Integer,
312320
* JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
313321
* @throws JSONException If syntax error.
314322
*
@@ -398,7 +406,11 @@ public Object nextValue() throws JSONException {
398406
return Long.valueOf(s);
399407
} catch (Exception f) {
400408
try {
401-
return new Double(s);
409+
if (useBigDecimal) {
410+
return new BigDecimal(s);
411+
} else {
412+
return new Double(s);
413+
}
402414
} catch (Exception g) {
403415
return s;
404416
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.codehaus.jettison.json;
2+
3+
import java.math.BigDecimal;
4+
5+
import junit.framework.TestCase;
6+
7+
public class JSONTokenerTest extends TestCase {
8+
9+
public void testDoublePrecision() throws Exception {
10+
JSONTokener doubleTokener = new JSONTokener("9999999999999.9999");
11+
Object nextValue = doubleTokener.nextValue();
12+
assertEquals(Double.class, nextValue.getClass());
13+
assertEquals(Double.valueOf("1.0E13"), nextValue);
14+
}
15+
16+
public void testBigDecimalPrecision() throws Exception {
17+
JSONTokener bigDecimalTokener = new JSONTokener("9999999999999.9999") {
18+
{
19+
this.useBigDecimal = true;
20+
}
21+
};
22+
Object nextValue = bigDecimalTokener.nextValue();
23+
assertEquals(BigDecimal.class, nextValue.getClass());
24+
assertEquals(new BigDecimal("9999999999999.9999"), nextValue);
25+
}
26+
27+
}

0 commit comments

Comments
 (0)