mirror of
https://github.com/stleary/JSON-java.git
synced 2025-08-03 03:15:32 -04:00
Merge pull request #337 from johnjaylward/OptimizeOpt
Optimizes opt* functions
This commit is contained in:
commit
fbd2be7431
239
JSONArray.java
239
JSONArray.java
@ -244,7 +244,50 @@ public class JSONArray implements Iterable<Object> {
|
||||
return object instanceof Number ? ((Number) object).doubleValue()
|
||||
: Double.parseDouble((String) object);
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the float value associated with a key.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The numeric value.
|
||||
* @throws JSONException
|
||||
* if the key is not found or if the value is not a Number
|
||||
* object and cannot be converted to a number.
|
||||
*/
|
||||
public float getFloat(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
try {
|
||||
return object instanceof Number ? ((Number) object).floatValue()
|
||||
: Float.parseFloat(object.toString());
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index
|
||||
+ "] is not a number.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Number value associated with a key.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The numeric value.
|
||||
* @throws JSONException
|
||||
* if the key is not found or if the value is not a Number
|
||||
* object and cannot be converted to a number.
|
||||
*/
|
||||
public Number getNumber(int index) throws JSONException {
|
||||
Object object = this.get(index);
|
||||
try {
|
||||
if (object instanceof Number) {
|
||||
return (Number)object;
|
||||
}
|
||||
return JSONObject.stringToNumber(object.toString());
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,9 +309,8 @@ public class JSONArray implements Iterable<Object> {
|
||||
// JSONException should really take a throwable argument.
|
||||
// If it did, I would re-implement this with the Enum.valueOf
|
||||
// method and place any thrown exception in the JSONException
|
||||
throw new JSONException("JSONObject[" + JSONObject.quote(Integer.toString(index))
|
||||
+ "] is not an enum of type " + JSONObject.quote(clazz.getSimpleName())
|
||||
+ ".");
|
||||
throw new JSONException("JSONArray[" + index + "] is not an enum of type "
|
||||
+ JSONObject.quote(clazz.getSimpleName()) + ".");
|
||||
}
|
||||
return val;
|
||||
}
|
||||
@ -289,7 +331,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
return new BigDecimal(object.toString());
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index +
|
||||
"] could not convert to BigDecimal.");
|
||||
"] could not convert to BigDecimal.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,7 +351,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
return new BigInteger(object.toString());
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index +
|
||||
"] could not convert to BigInteger.");
|
||||
"] could not convert to BigInteger.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,7 +370,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
return object instanceof Number ? ((Number) object).intValue()
|
||||
: Integer.parseInt((String) object);
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,7 +426,7 @@ public class JSONArray implements Iterable<Object> {
|
||||
return object instanceof Number ? ((Number) object).longValue()
|
||||
: Long.parseLong((String) object);
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.");
|
||||
throw new JSONException("JSONArray[" + index + "] is not a number.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -518,11 +560,63 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @return The value.
|
||||
*/
|
||||
public double optDouble(int index, double defaultValue) {
|
||||
try {
|
||||
return this.getDouble(index);
|
||||
} catch (Exception e) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof Number){
|
||||
return ((Number) val).doubleValue();
|
||||
}
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return Double.parseDouble((String) val);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional float value associated with an index. NaN is returned
|
||||
* if there is no value for the index, or if the value is not a number and
|
||||
* cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return The value.
|
||||
*/
|
||||
public float optFloat(int index) {
|
||||
return this.optFloat(index, Float.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional float value associated with an index. The defaultValue
|
||||
* is returned if there is no value for the index, or if the value is not a
|
||||
* number and cannot be converted to a number.
|
||||
*
|
||||
* @param index
|
||||
* subscript
|
||||
* @param defaultValue
|
||||
* The default value.
|
||||
* @return The value.
|
||||
*/
|
||||
public float optFloat(int index, float defaultValue) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof Number){
|
||||
return ((Number) val).floatValue();
|
||||
}
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return Float.parseFloat((String) val);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -550,11 +644,22 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @return The value.
|
||||
*/
|
||||
public int optInt(int index, int defaultValue) {
|
||||
try {
|
||||
return this.getInt(index);
|
||||
} catch (Exception e) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof Number){
|
||||
return ((Number) val).intValue();
|
||||
}
|
||||
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return new BigDecimal(val.toString()).intValue();
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -615,8 +720,29 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @return The value.
|
||||
*/
|
||||
public BigInteger optBigInteger(int index, BigInteger defaultValue) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
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 {
|
||||
return this.getBigInteger(index);
|
||||
final String valStr = val.toString();
|
||||
if(JSONObject.isDecimalNotation(valStr)) {
|
||||
return new BigDecimal(valStr).toBigInteger();
|
||||
}
|
||||
return new BigInteger(valStr);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
@ -634,8 +760,25 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @return The value.
|
||||
*/
|
||||
public BigDecimal optBigDecimal(int index, BigDecimal defaultValue) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
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 this.getBigDecimal(index);
|
||||
return new BigDecimal(val.toString());
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
@ -693,17 +836,73 @@ public class JSONArray implements Iterable<Object> {
|
||||
* @return The value.
|
||||
*/
|
||||
public long optLong(int index, long defaultValue) {
|
||||
try {
|
||||
return this.getLong(index);
|
||||
} catch (Exception e) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof Number){
|
||||
return ((Number) val).longValue();
|
||||
}
|
||||
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return new BigDecimal(val.toString()).longValue();
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an optional {@link Number} value associated with a key, or <code>null</code>
|
||||
* if there is no such key or if the value is not a number. If the value is a string,
|
||||
* an attempt will be made to evaluate it as a number ({@link BigDecimal}). This method
|
||||
* would be used in cases where type coercion of the number value is unwanted.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @return An object which is the value.
|
||||
*/
|
||||
public Number optNumber(int index) {
|
||||
return this.optNumber(index, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an optional {@link Number} value associated with a key, or the default if there
|
||||
* is no such key or if the value is not a number. If the value is a string,
|
||||
* an attempt will be made to evaluate it as a number ({@link BigDecimal}). This method
|
||||
* would be used in cases where type coercion of the number value is unwanted.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
* @param defaultValue
|
||||
* The default.
|
||||
* @return An object which is the value.
|
||||
*/
|
||||
public Number optNumber(int index, Number defaultValue) {
|
||||
Object val = this.opt(index);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof Number){
|
||||
return (Number) val;
|
||||
}
|
||||
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return JSONObject.stringToNumber((String) val);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional string value associated with an index. It returns an
|
||||
* empty string if there is no value at that index. If the value is not a
|
||||
* string and is not null, then it is coverted to a string.
|
||||
* string and is not null, then it is converted to a string.
|
||||
*
|
||||
* @param index
|
||||
* The index must be between 0 and length() - 1.
|
||||
|
410
JSONObject.java
410
JSONObject.java
@ -549,7 +549,7 @@ public class JSONObject {
|
||||
return new BigInteger(object.toString());
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONObject[" + quote(key)
|
||||
+ "] could not be converted to BigInteger.");
|
||||
+ "] could not be converted to BigInteger.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -565,11 +565,14 @@ public class JSONObject {
|
||||
*/
|
||||
public BigDecimal getBigDecimal(String key) throws JSONException {
|
||||
Object object = this.get(key);
|
||||
if (object instanceof BigDecimal) {
|
||||
return (BigDecimal)object;
|
||||
}
|
||||
try {
|
||||
return new BigDecimal(object.toString());
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONObject[" + quote(key)
|
||||
+ "] could not be converted to BigDecimal.");
|
||||
+ "] could not be converted to BigDecimal.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -587,10 +590,54 @@ public class JSONObject {
|
||||
Object object = this.get(key);
|
||||
try {
|
||||
return object instanceof Number ? ((Number) object).doubleValue()
|
||||
: Double.parseDouble((String) object);
|
||||
: Double.parseDouble(object.toString());
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONObject[" + quote(key)
|
||||
+ "] is not a number.");
|
||||
+ "] is not a number.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the float value associated with a key.
|
||||
*
|
||||
* @param key
|
||||
* A key string.
|
||||
* @return The numeric value.
|
||||
* @throws JSONException
|
||||
* if the key is not found or if the value is not a Number
|
||||
* object and cannot be converted to a number.
|
||||
*/
|
||||
public float getFloat(String key) throws JSONException {
|
||||
Object object = this.get(key);
|
||||
try {
|
||||
return object instanceof Number ? ((Number) object).floatValue()
|
||||
: Float.parseFloat(object.toString());
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONObject[" + quote(key)
|
||||
+ "] is not a number.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Number value associated with a key.
|
||||
*
|
||||
* @param key
|
||||
* A key string.
|
||||
* @return The numeric value.
|
||||
* @throws JSONException
|
||||
* if the key is not found or if the value is not a Number
|
||||
* object and cannot be converted to a number.
|
||||
*/
|
||||
public Number getNumber(String key) throws JSONException {
|
||||
Object object = this.get(key);
|
||||
try {
|
||||
if (object instanceof Number) {
|
||||
return (Number)object;
|
||||
}
|
||||
return stringToNumber(object.toString());
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONObject[" + quote(key)
|
||||
+ "] is not a number.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,7 +658,7 @@ public class JSONObject {
|
||||
: Integer.parseInt((String) object);
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONObject[" + quote(key)
|
||||
+ "] is not an int.");
|
||||
+ "] is not an int.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -668,7 +715,7 @@ public class JSONObject {
|
||||
: Long.parseLong((String) object);
|
||||
} catch (Exception e) {
|
||||
throw new JSONException("JSONObject[" + quote(key)
|
||||
+ "] is not a long.");
|
||||
+ "] is not a long.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -687,7 +734,7 @@ public class JSONObject {
|
||||
int i = 0;
|
||||
while (iterator.hasNext()) {
|
||||
names[i] = iterator.next();
|
||||
i += 1;
|
||||
i++;
|
||||
}
|
||||
return names;
|
||||
}
|
||||
@ -942,13 +989,104 @@ public class JSONObject {
|
||||
* @return The truth.
|
||||
*/
|
||||
public boolean optBoolean(String key, boolean defaultValue) {
|
||||
Object val = this.opt(key);
|
||||
if (NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof Boolean){
|
||||
return ((Boolean) val).booleanValue();
|
||||
}
|
||||
try {
|
||||
// we'll use the get anyway because it does string conversion.
|
||||
return this.getBoolean(key);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* string, an attempt will be made to evaluate it as a number.
|
||||
*
|
||||
* @param key
|
||||
* A key string.
|
||||
* @param defaultValue
|
||||
* The default.
|
||||
* @return An object which is the value.
|
||||
*/
|
||||
public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) {
|
||||
Object val = this.opt(key);
|
||||
if (NULL.equals(val)) {
|
||||
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());
|
||||
}
|
||||
// don't check if it's a string in case of unchecked Number subclasses
|
||||
try {
|
||||
return new BigDecimal(val.toString());
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an optional BigInteger 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
|
||||
* string, an attempt will be made to evaluate it as a number.
|
||||
*
|
||||
* @param key
|
||||
* A key string.
|
||||
* @param defaultValue
|
||||
* The default.
|
||||
* @return An object which is the value.
|
||||
*/
|
||||
public BigInteger optBigInteger(String key, BigInteger defaultValue) {
|
||||
Object val = this.opt(key);
|
||||
if (NULL.equals(val)) {
|
||||
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());
|
||||
}
|
||||
// don't check if it's a string in case of unchecked Number subclasses
|
||||
try {
|
||||
// the other opt functions handle implicit conversions, i.e.
|
||||
// jo.put("double",1.1d);
|
||||
// jo.optInt("double"); -- will return 1, not an error
|
||||
// this conversion to BigDecimal then to BigInteger is to maintain
|
||||
// that type cast support that may truncate the decimal.
|
||||
final String valStr = val.toString();
|
||||
if(isDecimalNotation(valStr)) {
|
||||
return new BigDecimal(valStr).toBigInteger();
|
||||
}
|
||||
return new BigInteger(valStr);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an optional double associated with a key, or NaN if there is no such
|
||||
* key or if its value is not a number. If the value is a string, an attempt
|
||||
@ -962,44 +1100,6 @@ public class JSONObject {
|
||||
return this.optDouble(key, Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an optional BigInteger 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
|
||||
* string, an attempt will be made to evaluate it as a number.
|
||||
*
|
||||
* @param key
|
||||
* A key string.
|
||||
* @param defaultValue
|
||||
* The default.
|
||||
* @return An object which is the value.
|
||||
*/
|
||||
public BigInteger optBigInteger(String key, BigInteger defaultValue) {
|
||||
try {
|
||||
return this.getBigInteger(key);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* string, an attempt will be made to evaluate it as a number.
|
||||
*
|
||||
* @param key
|
||||
* A key string.
|
||||
* @param defaultValue
|
||||
* The default.
|
||||
* @return An object which is the value.
|
||||
*/
|
||||
public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) {
|
||||
try {
|
||||
return this.getBigDecimal(key);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an optional double 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
|
||||
@ -1012,11 +1112,63 @@ public class JSONObject {
|
||||
* @return An object which is the value.
|
||||
*/
|
||||
public double optDouble(String key, double defaultValue) {
|
||||
try {
|
||||
return this.getDouble(key);
|
||||
} catch (Exception e) {
|
||||
Object val = this.opt(key);
|
||||
if (NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof Number){
|
||||
return ((Number) val).doubleValue();
|
||||
}
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return Double.parseDouble((String) val);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional double value associated with an index. NaN is returned
|
||||
* if there is no value for the index, or if the value is not a number and
|
||||
* cannot be converted to a number.
|
||||
*
|
||||
* @param key
|
||||
* A key string.
|
||||
* @return The value.
|
||||
*/
|
||||
public float optFloat(String key) {
|
||||
return this.optFloat(key, Float.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the optional double value associated with an index. The defaultValue
|
||||
* is returned if there is no value for the index, or if the value is not a
|
||||
* number and cannot be converted to a number.
|
||||
*
|
||||
* @param key
|
||||
* A key string.
|
||||
* @param defaultValue
|
||||
* The default value.
|
||||
* @return The value.
|
||||
*/
|
||||
public float optFloat(String key, float defaultValue) {
|
||||
Object val = this.opt(key);
|
||||
if (JSONObject.NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof Number){
|
||||
return ((Number) val).floatValue();
|
||||
}
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return Float.parseFloat((String) val);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1044,11 +1196,22 @@ public class JSONObject {
|
||||
* @return An object which is the value.
|
||||
*/
|
||||
public int optInt(String key, int defaultValue) {
|
||||
try {
|
||||
return this.getInt(key);
|
||||
} catch (Exception e) {
|
||||
Object val = this.opt(key);
|
||||
if (NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof Number){
|
||||
return ((Number) val).intValue();
|
||||
}
|
||||
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return new BigDecimal((String) val).intValue();
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1102,13 +1265,69 @@ public class JSONObject {
|
||||
* @return An object which is the value.
|
||||
*/
|
||||
public long optLong(String key, long defaultValue) {
|
||||
try {
|
||||
return this.getLong(key);
|
||||
} catch (Exception e) {
|
||||
Object val = this.opt(key);
|
||||
if (NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof Number){
|
||||
return ((Number) val).longValue();
|
||||
}
|
||||
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return new BigDecimal((String) val).longValue();
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an optional {@link Number} value associated with a key, or <code>null</code>
|
||||
* if there is no such key or if the value is not a number. If the value is a string,
|
||||
* an attempt will be made to evaluate it as a number ({@link BigDecimal}). This method
|
||||
* would be used in cases where type coercion of the number value is unwanted.
|
||||
*
|
||||
* @param key
|
||||
* A key string.
|
||||
* @return An object which is the value.
|
||||
*/
|
||||
public Number optNumber(String key) {
|
||||
return this.optNumber(key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an optional {@link Number} value associated with a key, or the default if there
|
||||
* is no such key or if the value is not a number. If the value is a string,
|
||||
* an attempt will be made to evaluate it as a number. This method
|
||||
* would be used in cases where type coercion of the number value is unwanted.
|
||||
*
|
||||
* @param key
|
||||
* A key string.
|
||||
* @param defaultValue
|
||||
* The default.
|
||||
* @return An object which is the value.
|
||||
*/
|
||||
public Number optNumber(String key, Number defaultValue) {
|
||||
Object val = this.opt(key);
|
||||
if (NULL.equals(val)) {
|
||||
return defaultValue;
|
||||
}
|
||||
if (val instanceof Number){
|
||||
return (Number) val;
|
||||
}
|
||||
|
||||
if (val instanceof String) {
|
||||
try {
|
||||
return stringToNumber((String) val);
|
||||
} catch (Exception e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an optional string associated with a key. It returns an empty string
|
||||
* if there is no such key. If the value is not a string and is not null,
|
||||
@ -1569,6 +1788,81 @@ public class JSONObject {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the value should be tried as a decimal. It makes no test if there are actual digits.
|
||||
*
|
||||
* @param val value to test
|
||||
* @return true if the string is "-0" or if it contains '.', 'e', or 'E', false otherwise.
|
||||
*/
|
||||
protected static boolean isDecimalNotation(final String val) {
|
||||
return val.indexOf('.') > -1 || val.indexOf('e') > -1
|
||||
|| val.indexOf('E') > -1 || "-0".equals(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string to a number using the narrowest possible type. Possible
|
||||
* returns for this function are BigDecimal, Double, BigInteger, Long, and Integer.
|
||||
* When a Double is returned, it should always be a valid Double and not NaN or +-infinity.
|
||||
*
|
||||
* @param val value to convert
|
||||
* @return Number representation of the value.
|
||||
* @throws NumberFormatException thrown if the value is not a valid number. A public
|
||||
* caller should catch this and wrap it in a {@link JSONException} if applicable.
|
||||
*/
|
||||
protected static Number stringToNumber(final String val) throws NumberFormatException {
|
||||
char initial = val.charAt(0);
|
||||
if ((initial >= '0' && initial <= '9') || initial == '-') {
|
||||
// decimal representation
|
||||
if (isDecimalNotation(val)) {
|
||||
// quick dirty way to see if we need a BigDecimal instead of a Double
|
||||
// this only handles some cases of overflow or underflow
|
||||
if (val.length()>14) {
|
||||
return new BigDecimal(val);
|
||||
}
|
||||
final Double d = Double.valueOf(val);
|
||||
if (d.isInfinite() || d.isNaN()) {
|
||||
// if we can't parse it as a double, go up to BigDecimal
|
||||
// this is probably due to underflow like 4.32e-678
|
||||
// or overflow like 4.65e5324. The size of the string is small
|
||||
// but can't be held in a Double.
|
||||
return new BigDecimal(val);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
// integer representation.
|
||||
// This will narrow any values to the smallest reasonable Object representation
|
||||
// (Integer, Long, or BigInteger)
|
||||
|
||||
// string version
|
||||
// The compare string length method reduces GC,
|
||||
// but leads to smaller integers being placed in larger wrappers even though not
|
||||
// needed. i.e. 1,000,000,000 -> Long even though it's an Integer
|
||||
// 1,000,000,000,000,000,000 -> BigInteger even though it's a Long
|
||||
//if(val.length()<=9){
|
||||
// return Integer.valueOf(val);
|
||||
//}
|
||||
//if(val.length()<=18){
|
||||
// return Long.valueOf(val);
|
||||
//}
|
||||
//return new BigInteger(val);
|
||||
|
||||
// BigInteger version: We use a similar bitLenth compare as
|
||||
// BigInteger#intValueExact uses. Increases GC, but objects hold
|
||||
// only what they need. i.e. Less runtime overhead if the value is
|
||||
// long lived. Which is the better tradeoff? This is closer to what's
|
||||
// in stringToValue.
|
||||
BigInteger bi = new BigInteger(val);
|
||||
if(bi.bitLength()<=31){
|
||||
return Integer.valueOf(bi.intValue());
|
||||
}
|
||||
if(bi.bitLength()<=63){
|
||||
return Long.valueOf(bi.longValue());
|
||||
}
|
||||
return bi;
|
||||
}
|
||||
throw new NumberFormatException("val ["+val+"] is not a valid number.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to convert a string into a number, boolean, or null. If the string
|
||||
@ -1600,15 +1894,15 @@ public class JSONObject {
|
||||
char initial = string.charAt(0);
|
||||
if ((initial >= '0' && initial <= '9') || initial == '-') {
|
||||
try {
|
||||
if (string.indexOf('.') > -1 || string.indexOf('e') > -1
|
||||
|| string.indexOf('E') > -1
|
||||
|| "-0".equals(string)) {
|
||||
// if we want full Big Number support this block can be replaced with:
|
||||
// return stringToNumber(string);
|
||||
if (isDecimalNotation(string)) {
|
||||
Double d = Double.valueOf(string);
|
||||
if (!d.isInfinite() && !d.isNaN()) {
|
||||
return d;
|
||||
}
|
||||
} else {
|
||||
Long myLong = new Long(string);
|
||||
Long myLong = Long.valueOf(string);
|
||||
if (string.equals(myLong.toString())) {
|
||||
if (myLong.longValue() == myLong.intValue()) {
|
||||
return Integer.valueOf(myLong.intValue());
|
||||
|
Loading…
x
Reference in New Issue
Block a user