Skip to content

Commit

Permalink
Use BigDecimal instead of Double to avoid loss of precision
Browse files Browse the repository at this point in the history
  • Loading branch information
ind1go authored and dkulp committed Jun 9, 2022
1 parent 23a64ee commit d371468
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
16 changes: 14 additions & 2 deletions src/main/java/org/codehaus/jettison/json/JSONTokener.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package org.codehaus.jettison.json;

import java.math.BigDecimal;

/**
* A JSONTokener takes a source string and extracts characters and tokens from
* it. It is used by the JSONObject and JSONArray constructors to parse
Expand All @@ -24,6 +26,11 @@
*/
public class JSONTokener {

private static final String USE_BIGDECIMAL_JSONTOKENER_KEY = "jettison.json.jsontokener.use_bigdecimal";
public static final boolean USE_BIGDECIMAL_JSONTOKENER = Boolean.getBoolean( USE_BIGDECIMAL_JSONTOKENER_KEY );
protected boolean useBigDecimal = USE_BIGDECIMAL_JSONTOKENER;


/**
* The index of the next character.
*/
Expand Down Expand Up @@ -308,7 +315,8 @@ public String nextTo(String delimiters) {


/**
* Get the next value. The value can be a Boolean, Double, Integer,
* Get the next value. The value can be a Boolean, Double/BigDecimal
* (depending on -Djettison.json.jsontokener.use_bigdecimal), Integer,
* JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
* @throws JSONException If syntax error.
*
Expand Down Expand Up @@ -398,7 +406,11 @@ public Object nextValue() throws JSONException {
return Long.valueOf(s);
} catch (Exception f) {
try {
return new Double(s);
if (useBigDecimal) {
return new BigDecimal(s);
} else {
return new Double(s);
}
} catch (Exception g) {
return s;
}
Expand Down
27 changes: 27 additions & 0 deletions src/test/java/org/codehaus/jettison/json/JSONTokenerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.codehaus.jettison.json;

import java.math.BigDecimal;

import junit.framework.TestCase;

public class JSONTokenerTest extends TestCase {

public void testDoublePrecision() throws Exception {
JSONTokener doubleTokener = new JSONTokener("9999999999999.9999");
Object nextValue = doubleTokener.nextValue();
assertEquals(Double.class, nextValue.getClass());
assertEquals(Double.valueOf("1.0E13"), nextValue);
}

public void testBigDecimalPrecision() throws Exception {
JSONTokener bigDecimalTokener = new JSONTokener("9999999999999.9999") {
{
this.useBigDecimal = true;
}
};
Object nextValue = bigDecimalTokener.nextValue();
assertEquals(BigDecimal.class, nextValue.getClass());
assertEquals(new BigDecimal("9999999999999.9999"), nextValue);
}

}

0 comments on commit d371468

Please sign in to comment.