diff --git a/JSONArray.java b/JSONArray.java index 537abb134..d46a76866 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -249,7 +249,7 @@ public boolean getBoolean(int index) throws JSONException { .equalsIgnoreCase("true"))) { return true; } - throw new JSONException("JSONArray[" + index + "] is not a boolean."); + throw wrongValueFormatException(index, "boolean", null); } /** @@ -263,7 +263,15 @@ public boolean getBoolean(int index) throws JSONException { * to a number. */ public double getDouble(int index) throws JSONException { - return this.getNumber(index).doubleValue(); + final Object object = this.get(index); + if(object instanceof Number) { + return ((Number)object).doubleValue(); + } + try { + return Double.parseDouble(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(index, "double", e); + } } /** @@ -277,7 +285,15 @@ public double getDouble(int index) throws JSONException { * object and cannot be converted to a number. */ public float getFloat(int index) throws JSONException { - return this.getNumber(index).floatValue(); + final Object object = this.get(index); + if(object instanceof Number) { + return ((Float)object).floatValue(); + } + try { + return Float.parseFloat(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(index, "float", e); + } } /** @@ -298,7 +314,7 @@ public Number getNumber(int index) throws JSONException { } return JSONObject.stringToNumber(object.toString()); } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number.", e); + throw wrongValueFormatException(index, "number", e); } } @@ -322,8 +338,8 @@ public > E getEnum(Class clazz, int index) throws JSONExcep // 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("JSONArray[" + index + "] is not an enum of type " - + JSONObject.quote(clazz.getSimpleName()) + "."); + throw wrongValueFormatException(index, "enum of type " + + JSONObject.quote(clazz.getSimpleName()), null); } return val; } @@ -345,8 +361,7 @@ public BigDecimal getBigDecimal (int index) throws JSONException { Object object = this.get(index); BigDecimal val = JSONObject.objectToBigDecimal(object, null); if(val == null) { - throw new JSONException("JSONArray[" + index + - "] could not convert to BigDecimal ("+ object + ")."); + throw wrongValueFormatException(index, "BigDecimal", object, null); } return val; } @@ -365,8 +380,7 @@ public BigInteger getBigInteger (int index) throws JSONException { Object object = this.get(index); BigInteger val = JSONObject.objectToBigInteger(object, null); if(val == null) { - throw new JSONException("JSONArray[" + index + - "] could not convert to BigDecimal ("+ object + ")."); + throw wrongValueFormatException(index, "BigInteger", object, null); } return val; } @@ -381,7 +395,15 @@ public BigInteger getBigInteger (int index) throws JSONException { * If the key is not found or if the value is not a number. */ public int getInt(int index) throws JSONException { - return this.getNumber(index).intValue(); + final Object object = this.get(index); + if(object instanceof Number) { + return ((Number)object).intValue(); + } + try { + return Integer.parseInt(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(index, "int", e); + } } /** @@ -399,7 +421,7 @@ public JSONArray getJSONArray(int index) throws JSONException { if (object instanceof JSONArray) { return (JSONArray) object; } - throw new JSONException("JSONArray[" + index + "] is not a JSONArray."); + throw wrongValueFormatException(index, "JSONArray", null); } /** @@ -417,7 +439,7 @@ public JSONObject getJSONObject(int index) throws JSONException { if (object instanceof JSONObject) { return (JSONObject) object; } - throw new JSONException("JSONArray[" + index + "] is not a JSONObject."); + throw wrongValueFormatException(index, "JSONObject", null); } /** @@ -431,7 +453,15 @@ public JSONObject getJSONObject(int index) throws JSONException { * to a number. */ public long getLong(int index) throws JSONException { - return this.getNumber(index).longValue(); + final Object object = this.get(index); + if(object instanceof Number) { + return ((Number)object).longValue(); + } + try { + return Long.parseLong(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(index, "long", e); + } } /** @@ -448,7 +478,7 @@ public String getString(int index) throws JSONException { if (object instanceof String) { return (String) object; } - throw new JSONException("JSONArray[" + index + "] not a string."); + throw wrongValueFormatException(index, "String", null); } /** @@ -1454,5 +1484,38 @@ public List toList() { public boolean isEmpty() { return this.myArrayList.isEmpty(); } + + /** + * Create a new JSONException in a common format for incorrect conversions. + * @param idx index of the item + * @param valueType the type of value being coerced to + * @param cause optional cause of the coercion failure + * @return JSONException that can be thrown. + */ + private static JSONException wrongValueFormatException( + int idx, + String valueType, + Throwable cause) { + return new JSONException( + "JSONArray[" + idx + "] is not a " + valueType + "." + , cause); + } + + /** + * Create a new JSONException in a common format for incorrect conversions. + * @param idx index of the item + * @param valueType the type of value being coerced to + * @param cause optional cause of the coercion failure + * @return JSONException that can be thrown. + */ + private static JSONException wrongValueFormatException( + int idx, + String valueType, + Object value, + Throwable cause) { + return new JSONException( + "JSONArray[" + idx + "] is not a " + valueType + " (" + value + ")." + , cause); + } } diff --git a/JSONObject.java b/JSONObject.java index c54018e15..678a5d67b 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -521,8 +521,7 @@ public JSONObject append(String key, Object value) throws JSONException { } else if (object instanceof JSONArray) { this.put(key, ((JSONArray) object).put(value)); } else { - throw new JSONException("JSONObject[" + key - + "] is not a JSONArray."); + throw wrongValueFormatException(key, "JSONArray", null, null); } return this; } @@ -595,9 +594,7 @@ public > E getEnum(Class clazz, String key) throws JSONExce // 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[" + quote(key) - + "] is not an enum of type " + quote(clazz.getSimpleName()) - + "."); + throw wrongValueFormatException(key, "enum of type " + quote(clazz.getSimpleName()), null); } return val; } @@ -623,8 +620,7 @@ public boolean getBoolean(String key) throws JSONException { .equalsIgnoreCase("true"))) { return true; } - throw new JSONException("JSONObject[" + quote(key) - + "] is not a Boolean."); + throw wrongValueFormatException(key, "Boolean", null); } /** @@ -643,8 +639,7 @@ public BigInteger getBigInteger(String key) throws JSONException { if (ret != null) { return ret; } - throw new JSONException("JSONObject[" + quote(key) - + "] could not be converted to BigInteger (" + object + ")."); + throw wrongValueFormatException(key, "BigInteger", object, null); } /** @@ -666,8 +661,7 @@ public BigDecimal getBigDecimal(String key) throws JSONException { if (ret != null) { return ret; } - throw new JSONException("JSONObject[" + quote(key) - + "] could not be converted to BigDecimal (" + object + ")."); + throw wrongValueFormatException(key, "BigDecimal", object, null); } /** @@ -681,7 +675,15 @@ public BigDecimal getBigDecimal(String key) throws JSONException { * object and cannot be converted to a number. */ public double getDouble(String key) throws JSONException { - return this.getNumber(key).doubleValue(); + final Object object = this.get(key); + if(object instanceof Number) { + return ((Number)object).doubleValue(); + } + try { + return Double.parseDouble(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(key, "double", e); + } } /** @@ -695,7 +697,15 @@ public double getDouble(String key) throws JSONException { * object and cannot be converted to a number. */ public float getFloat(String key) throws JSONException { - return this.getNumber(key).floatValue(); + final Object object = this.get(key); + if(object instanceof Number) { + return ((Number)object).floatValue(); + } + try { + return Float.parseFloat(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(key, "float", e); + } } /** @@ -716,8 +726,7 @@ public Number getNumber(String key) throws JSONException { } return stringToNumber(object.toString()); } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) - + "] is not a number.", e); + throw wrongValueFormatException(key, "number", e); } } @@ -732,7 +741,15 @@ public Number getNumber(String key) throws JSONException { * to an integer. */ public int getInt(String key) throws JSONException { - return this.getNumber(key).intValue(); + final Object object = this.get(key); + if(object instanceof Number) { + return ((Number)object).intValue(); + } + try { + return Integer.parseInt(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(key, "int", e); + } } /** @@ -749,8 +766,7 @@ public JSONArray getJSONArray(String key) throws JSONException { if (object instanceof JSONArray) { return (JSONArray) object; } - throw new JSONException("JSONObject[" + quote(key) - + "] is not a JSONArray."); + throw wrongValueFormatException(key, "JSONArray", null); } /** @@ -767,8 +783,7 @@ public JSONObject getJSONObject(String key) throws JSONException { if (object instanceof JSONObject) { return (JSONObject) object; } - throw new JSONException("JSONObject[" + quote(key) - + "] is not a JSONObject."); + throw wrongValueFormatException(key, "JSONObject", null); } /** @@ -782,7 +797,15 @@ public JSONObject getJSONObject(String key) throws JSONException { * to a long. */ public long getLong(String key) throws JSONException { - return this.getNumber(key).longValue(); + final Object object = this.get(key); + if(object instanceof Number) { + return ((Number)object).longValue(); + } + try { + return Long.parseLong(object.toString()); + } catch (Exception e) { + throw wrongValueFormatException(key, "long", e); + } } /** @@ -837,7 +860,7 @@ public String getString(String key) throws JSONException { if (object instanceof String) { return (String) object; } - throw new JSONException("JSONObject[" + quote(key) + "] not a string."); + throw wrongValueFormatException(key, "string", null); } /** @@ -853,8 +876,11 @@ public boolean has(String key) { /** * Increment a property of a JSONObject. If there is no such property, - * create one with a value of 1. If there is such a property, and if it is - * an Integer, Long, Double, or Float, then add one to it. + * create one with a value of 1 (Integer). If there is such a property, and if it is + * an Integer, Long, Double, Float, BigInteger, or BigDecimal then add one to it. + * No overflow bounds checking is performed, so callers should initialize the key + * prior to this call with an appropriate type that can handle the maximum expected + * value. * * @param key * A key string. @@ -867,18 +893,18 @@ public JSONObject increment(String key) throws JSONException { Object value = this.opt(key); if (value == null) { this.put(key, 1); - } else if (value instanceof BigInteger) { - this.put(key, ((BigInteger)value).add(BigInteger.ONE)); - } else if (value instanceof BigDecimal) { - this.put(key, ((BigDecimal)value).add(BigDecimal.ONE)); } else if (value instanceof Integer) { this.put(key, ((Integer) value).intValue() + 1); } else if (value instanceof Long) { this.put(key, ((Long) value).longValue() + 1L); - } else if (value instanceof Double) { - this.put(key, ((Double) value).doubleValue() + 1.0d); + } else if (value instanceof BigInteger) { + this.put(key, ((BigInteger)value).add(BigInteger.ONE)); } else if (value instanceof Float) { this.put(key, ((Float) value).floatValue() + 1.0f); + } else if (value instanceof Double) { + this.put(key, ((Double) value).doubleValue() + 1.0d); + } else if (value instanceof BigDecimal) { + this.put(key, ((BigDecimal)value).add(BigDecimal.ONE)); } else { throw new JSONException("Unable to increment [" + quote(key) + "]."); } @@ -2548,4 +2574,37 @@ public Map toMap() { } return results; } + + /** + * Create a new JSONException in a common format for incorrect conversions. + * @param key name of the key + * @param valueType the type of value being coerced to + * @param cause optional cause of the coercion failure + * @return JSONException that can be thrown. + */ + private static JSONException wrongValueFormatException( + String key, + String valueType, + Throwable cause) { + return new JSONException( + "JSONObject[" + quote(key) + "] is not a " + valueType + "." + , cause); + } + + /** + * Create a new JSONException in a common format for incorrect conversions. + * @param key name of the key + * @param valueType the type of value being coerced to + * @param cause optional cause of the coercion failure + * @return JSONException that can be thrown. + */ + private static JSONException wrongValueFormatException( + String key, + String valueType, + Object value, + Throwable cause) { + return new JSONException( + "JSONObject[" + quote(key) + "] is not a " + valueType + " (" + value + ")." + , cause); + } }