mirror of
https://github.com/ethauvin/JSON-java.git
synced 2025-06-17 07:50:52 -07:00
* Fixes opt/getBigDecimal to be consistent
* Performance: Updates JSONWriter to use a regex to decide if writing as a number is best.
This commit is contained in:
parent
16225efbdd
commit
a63fa03062
3 changed files with 69 additions and 85 deletions
|
@ -345,12 +345,12 @@ public class JSONArray implements Iterable<Object> {
|
||||||
*/
|
*/
|
||||||
public BigDecimal getBigDecimal (int index) throws JSONException {
|
public BigDecimal getBigDecimal (int index) throws JSONException {
|
||||||
Object object = this.get(index);
|
Object object = this.get(index);
|
||||||
try {
|
BigDecimal val = JSONObject.objectToBigDecimal(object, null);
|
||||||
return new BigDecimal(object.toString());
|
if(val == null) {
|
||||||
} catch (Exception e) {
|
|
||||||
throw new JSONException("JSONArray[" + index +
|
throw new JSONException("JSONArray[" + index +
|
||||||
"] could not convert to BigDecimal.", e);
|
"] could not convert to BigDecimal ("+ object + ").");
|
||||||
}
|
}
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -365,12 +365,12 @@ public class JSONArray implements Iterable<Object> {
|
||||||
*/
|
*/
|
||||||
public BigInteger getBigInteger (int index) throws JSONException {
|
public BigInteger getBigInteger (int index) throws JSONException {
|
||||||
Object object = this.get(index);
|
Object object = this.get(index);
|
||||||
try {
|
BigInteger val = JSONObject.objectToBigInteger(object, null);
|
||||||
return new BigInteger(object.toString());
|
if(val == null) {
|
||||||
} catch (Exception e) {
|
|
||||||
throw new JSONException("JSONArray[" + index +
|
throw new JSONException("JSONArray[" + index +
|
||||||
"] could not convert to BigInteger.", e);
|
"] could not convert to BigDecimal ("+ object + ").");
|
||||||
}
|
}
|
||||||
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -739,31 +739,7 @@ public class JSONArray implements Iterable<Object> {
|
||||||
*/
|
*/
|
||||||
public BigInteger optBigInteger(int index, BigInteger defaultValue) {
|
public BigInteger optBigInteger(int index, BigInteger defaultValue) {
|
||||||
Object val = this.opt(index);
|
Object val = this.opt(index);
|
||||||
if (JSONObject.NULL.equals(val)) {
|
return JSONObject.objectToBigInteger(val, defaultValue);
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
if (val instanceof BigInteger){
|
|
||||||
return (BigInteger) val;
|
|
||||||
}
|
|
||||||
if (val instanceof BigDecimal){
|
|
||||||
return ((BigDecimal) val).toBigInteger();
|
|
||||||
}
|
|
||||||
if (val instanceof Double || val instanceof Float){
|
|
||||||
return new BigDecimal(((Number) val).doubleValue()).toBigInteger();
|
|
||||||
}
|
|
||||||
if (val instanceof Long || val instanceof Integer
|
|
||||||
|| val instanceof Short || val instanceof Byte){
|
|
||||||
return BigInteger.valueOf(((Number) val).longValue());
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
final String valStr = val.toString();
|
|
||||||
if(JSONObject.isDecimalNotation(valStr)) {
|
|
||||||
return new BigDecimal(valStr).toBigInteger();
|
|
||||||
}
|
|
||||||
return new BigInteger(valStr);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -779,27 +755,7 @@ public class JSONArray implements Iterable<Object> {
|
||||||
*/
|
*/
|
||||||
public BigDecimal optBigDecimal(int index, BigDecimal defaultValue) {
|
public BigDecimal optBigDecimal(int index, BigDecimal defaultValue) {
|
||||||
Object val = this.opt(index);
|
Object val = this.opt(index);
|
||||||
if (JSONObject.NULL.equals(val)) {
|
return JSONObject.objectToBigDecimal(val, defaultValue);
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
if (val instanceof BigDecimal){
|
|
||||||
return (BigDecimal) val;
|
|
||||||
}
|
|
||||||
if (val instanceof BigInteger){
|
|
||||||
return new BigDecimal((BigInteger) val);
|
|
||||||
}
|
|
||||||
if (val instanceof Double || val instanceof Float){
|
|
||||||
return new BigDecimal(((Number) val).doubleValue());
|
|
||||||
}
|
|
||||||
if (val instanceof Long || val instanceof Integer
|
|
||||||
|| val instanceof Short || val instanceof Byte){
|
|
||||||
return new BigDecimal(((Number) val).longValue());
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return new BigDecimal(val.toString());
|
|
||||||
} catch (Exception e) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -45,6 +45,7 @@ import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JSONObject is an unordered collection of name/value pairs. Its external
|
* A JSONObject is an unordered collection of name/value pairs. Its external
|
||||||
|
@ -150,6 +151,12 @@ public class JSONObject {
|
||||||
return "null";
|
return "null";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Regular Expression Pattern that matches JSON Numbers. This is primarily used for
|
||||||
|
* output to guarantee that we are always writing valid JSON.
|
||||||
|
*/
|
||||||
|
static final Pattern NUMBER_PATTERN = Pattern.compile("-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The map where the JSONObject's properties are kept.
|
* The map where the JSONObject's properties are kept.
|
||||||
|
@ -630,16 +637,19 @@ public class JSONObject {
|
||||||
*/
|
*/
|
||||||
public BigInteger getBigInteger(String key) throws JSONException {
|
public BigInteger getBigInteger(String key) throws JSONException {
|
||||||
Object object = this.get(key);
|
Object object = this.get(key);
|
||||||
try {
|
BigInteger ret = objectToBigInteger(object, null);
|
||||||
return new BigInteger(object.toString());
|
if (ret != null) {
|
||||||
} catch (Exception e) {
|
return ret;
|
||||||
throw new JSONException("JSONObject[" + quote(key)
|
|
||||||
+ "] could not be converted to BigInteger.", e);
|
|
||||||
}
|
}
|
||||||
|
throw new JSONException("JSONObject[" + quote(key)
|
||||||
|
+ "] could not be converted to BigInteger (" + object + ").");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the BigDecimal value associated with a key.
|
* Get the BigDecimal value associated with a key. If the value is float or
|
||||||
|
* double, the the {@link BigDecimal#BigDecimal(double)} constructor will
|
||||||
|
* be used. See notes on the constructor for conversion issues that may
|
||||||
|
* arise.
|
||||||
*
|
*
|
||||||
* @param key
|
* @param key
|
||||||
* A key string.
|
* A key string.
|
||||||
|
@ -650,15 +660,12 @@ public class JSONObject {
|
||||||
*/
|
*/
|
||||||
public BigDecimal getBigDecimal(String key) throws JSONException {
|
public BigDecimal getBigDecimal(String key) throws JSONException {
|
||||||
Object object = this.get(key);
|
Object object = this.get(key);
|
||||||
if (object instanceof BigDecimal) {
|
BigDecimal ret = objectToBigDecimal(object, null);
|
||||||
return (BigDecimal)object;
|
if (ret != null) {
|
||||||
}
|
return ret;
|
||||||
try {
|
|
||||||
return new BigDecimal(object.toString());
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new JSONException("JSONObject[" + quote(key)
|
|
||||||
+ "] could not be converted to BigDecimal.", e);
|
|
||||||
}
|
}
|
||||||
|
throw new JSONException("JSONObject[" + quote(key)
|
||||||
|
+ "] could not be converted to BigDecimal (" + object + ").");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -968,7 +975,7 @@ public class JSONObject {
|
||||||
* @return true if JSONObject is empty, otherwise false.
|
* @return true if JSONObject is empty, otherwise false.
|
||||||
*/
|
*/
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return map.isEmpty();
|
return this.map.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1113,7 +1120,10 @@ public class JSONObject {
|
||||||
/**
|
/**
|
||||||
* Get an optional BigDecimal associated with a key, or the defaultValue if
|
* Get an optional BigDecimal associated with a key, or the defaultValue if
|
||||||
* there is no such key or if its value is not a number. If the value is a
|
* there is no such key or if its value is not a number. If the value is a
|
||||||
* string, an attempt will be made to evaluate it as a number.
|
* string, an attempt will be made to evaluate it as a number. If the value
|
||||||
|
* is float or double, then the {@link BigDecimal#BigDecimal(double)}
|
||||||
|
* constructor will be used. See notes on the constructor for conversion
|
||||||
|
* issues that may arise.
|
||||||
*
|
*
|
||||||
* @param key
|
* @param key
|
||||||
* A key string.
|
* A key string.
|
||||||
|
@ -1123,6 +1133,15 @@ public class JSONObject {
|
||||||
*/
|
*/
|
||||||
public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) {
|
public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) {
|
||||||
Object val = this.opt(key);
|
Object val = this.opt(key);
|
||||||
|
return objectToBigDecimal(val, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param defaultValue
|
||||||
|
* @param val
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue) {
|
||||||
if (NULL.equals(val)) {
|
if (NULL.equals(val)) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
@ -1133,6 +1152,10 @@ public class JSONObject {
|
||||||
return new BigDecimal((BigInteger) val);
|
return new BigDecimal((BigInteger) val);
|
||||||
}
|
}
|
||||||
if (val instanceof Double || val instanceof Float){
|
if (val instanceof Double || val instanceof Float){
|
||||||
|
final double d = ((Number) val).doubleValue();
|
||||||
|
if(Double.isNaN(d)) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
return new BigDecimal(((Number) val).doubleValue());
|
return new BigDecimal(((Number) val).doubleValue());
|
||||||
}
|
}
|
||||||
if (val instanceof Long || val instanceof Integer
|
if (val instanceof Long || val instanceof Integer
|
||||||
|
@ -1160,6 +1183,15 @@ public class JSONObject {
|
||||||
*/
|
*/
|
||||||
public BigInteger optBigInteger(String key, BigInteger defaultValue) {
|
public BigInteger optBigInteger(String key, BigInteger defaultValue) {
|
||||||
Object val = this.opt(key);
|
Object val = this.opt(key);
|
||||||
|
return objectToBigInteger(val, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param defaultValue
|
||||||
|
* @param val
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static BigInteger objectToBigInteger(Object val, BigInteger defaultValue) {
|
||||||
if (NULL.equals(val)) {
|
if (NULL.equals(val)) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
@ -1170,7 +1202,11 @@ public class JSONObject {
|
||||||
return ((BigDecimal) val).toBigInteger();
|
return ((BigDecimal) val).toBigInteger();
|
||||||
}
|
}
|
||||||
if (val instanceof Double || val instanceof Float){
|
if (val instanceof Double || val instanceof Float){
|
||||||
return new BigDecimal(((Number) val).doubleValue()).toBigInteger();
|
final double d = ((Number) val).doubleValue();
|
||||||
|
if(Double.isNaN(d)) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
return new BigDecimal(d).toBigInteger();
|
||||||
}
|
}
|
||||||
if (val instanceof Long || val instanceof Integer
|
if (val instanceof Long || val instanceof Integer
|
||||||
|| val instanceof Short || val instanceof Byte){
|
|| val instanceof Short || val instanceof Byte){
|
||||||
|
@ -2414,13 +2450,9 @@ public class JSONObject {
|
||||||
} else if (value instanceof Number) {
|
} else if (value instanceof Number) {
|
||||||
// not all Numbers may match actual JSON Numbers. i.e. fractions or Imaginary
|
// not all Numbers may match actual JSON Numbers. i.e. fractions or Imaginary
|
||||||
final String numberAsString = numberToString((Number) value);
|
final String numberAsString = numberToString((Number) value);
|
||||||
try {
|
if(NUMBER_PATTERN.matcher(numberAsString).matches()) {
|
||||||
// Use the BigDecimal constructor for its parser to validate the format.
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
BigDecimal testNum = new BigDecimal(numberAsString);
|
|
||||||
// Close enough to a JSON number that we will use it unquoted
|
|
||||||
writer.write(numberAsString);
|
writer.write(numberAsString);
|
||||||
} catch (NumberFormatException ex){
|
} else {
|
||||||
// The Number value is not a valid JSON number.
|
// The Number value is not a valid JSON number.
|
||||||
// Instead we will quote it as a string
|
// Instead we will quote it as a string
|
||||||
quote(numberAsString, writer);
|
quote(numberAsString, writer);
|
||||||
|
|
|
@ -340,17 +340,13 @@ public class JSONWriter {
|
||||||
if (value instanceof Number) {
|
if (value instanceof Number) {
|
||||||
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
|
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
|
||||||
final String numberAsString = JSONObject.numberToString((Number) value);
|
final String numberAsString = JSONObject.numberToString((Number) value);
|
||||||
try {
|
if(JSONObject.NUMBER_PATTERN.matcher(numberAsString).matches()) {
|
||||||
// Use the BigDecimal constructor for it's parser to validate the format.
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
BigDecimal unused = new BigDecimal(numberAsString);
|
|
||||||
// Close enough to a JSON number that we will return it unquoted
|
// Close enough to a JSON number that we will return it unquoted
|
||||||
return numberAsString;
|
return numberAsString;
|
||||||
} catch (NumberFormatException ex){
|
|
||||||
// The Number value is not a valid JSON number.
|
|
||||||
// Instead we will quote it as a string
|
|
||||||
return JSONObject.quote(numberAsString);
|
|
||||||
}
|
}
|
||||||
|
// The Number value is not a valid JSON number.
|
||||||
|
// Instead we will quote it as a string
|
||||||
|
return JSONObject.quote(numberAsString);
|
||||||
}
|
}
|
||||||
if (value instanceof Boolean || value instanceof JSONObject
|
if (value instanceof Boolean || value instanceof JSONObject
|
||||||
|| value instanceof JSONArray) {
|
|| value instanceof JSONArray) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue