X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Forg%2Fjson%2FJSONArray.java;fp=src%2Forg%2Fjson%2FJSONArray.java;h=3f6c88e83c4e3e6d5c149e6dc7ca0211143ca02e;hb=3459a8a691cb22508d7067f240b7254e588e77d3;hp=fbc1a0f737b69bb01d269f642ed13acbae48a12c;hpb=5b27f1062b2203c4c31702e205f4c78e1992063e;p=jalview.git diff --git a/src/org/json/JSONArray.java b/src/org/json/JSONArray.java index fbc1a0f..3f6c88e 100644 --- a/src/org/json/JSONArray.java +++ b/src/org/json/JSONArray.java @@ -36,7 +36,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; - /** * A JSONArray is an ordered sequence of values. Its external text form is a * string wrapped in square brackets with commas separating the values. The @@ -73,1469 +72,1715 @@ import java.util.Map; *
  • Strings do not need to be quoted at all if they do not begin with a quote * or single quote, and if they do not contain leading or trailing spaces, and * if they do not contain any of these characters: - * { } [ ] / \ : , # and if they do not look like numbers and - * if they are not the reserved words true, false, or + * { } [ ] / \ : , # and if they do not look like numbers and if + * they are not the reserved words true, false, or * null.
  • * * * @author JSON.org * @version 2016-08/15 */ -public class JSONArray implements Iterable { - - /** - * The arrayList where the JSONArray's properties are kept. - */ - private final ArrayList myArrayList; - - /** - * Construct an empty JSONArray. - */ - public JSONArray() { - this.myArrayList = new ArrayList(); - } - - /** - * Construct a JSONArray from a JSONTokener. - * - * @param x - * A JSONTokener - * @throws JSONException - * If there is a syntax error. - */ - public JSONArray(JSONTokener x) throws JSONException { - this(); - if (x.nextClean() != '[') { - throw x.syntaxError("A JSONArray text must start with '['"); +public class JSONArray implements Iterable +{ + + /** + * The arrayList where the JSONArray's properties are kept. + */ + private final ArrayList myArrayList; + + /** + * Construct an empty JSONArray. + */ + public JSONArray() + { + this.myArrayList = new ArrayList(); + } + + /** + * Construct a JSONArray from a JSONTokener. + * + * @param x + * A JSONTokener + * @throws JSONException + * If there is a syntax error. + */ + public JSONArray(JSONTokener x) throws JSONException + { + this(); + if (x.nextClean() != '[') + { + throw x.syntaxError("A JSONArray text must start with '['"); + } + + char nextChar = x.nextClean(); + if (nextChar == 0) + { + // array is unclosed. No ']' found, instead EOF + throw x.syntaxError("Expected a ',' or ']'"); + } + if (nextChar != ']') + { + x.back(); + for (;;) + { + if (x.nextClean() == ',') + { + x.back(); + this.myArrayList.add(JSONObject.NULL); + } + else + { + x.back(); + this.myArrayList.add(x.nextValue()); } - - char nextChar = x.nextClean(); - if (nextChar == 0) { + switch (x.nextClean()) + { + case 0: + // array is unclosed. No ']' found, instead EOF + throw x.syntaxError("Expected a ',' or ']'"); + case ',': + nextChar = x.nextClean(); + if (nextChar == 0) + { // array is unclosed. No ']' found, instead EOF throw x.syntaxError("Expected a ',' or ']'"); + } + if (nextChar == ']') + { + return; + } + x.back(); + break; + case ']': + return; + default: + throw x.syntaxError("Expected a ',' or ']'"); } - if (nextChar != ']') { - x.back(); - for (;;) { - if (x.nextClean() == ',') { - x.back(); - this.myArrayList.add(JSONObject.NULL); - } else { - x.back(); - this.myArrayList.add(x.nextValue()); - } - switch (x.nextClean()) { - case 0: - // array is unclosed. No ']' found, instead EOF - throw x.syntaxError("Expected a ',' or ']'"); - case ',': - nextChar = x.nextClean(); - if (nextChar == 0) { - // array is unclosed. No ']' found, instead EOF - throw x.syntaxError("Expected a ',' or ']'"); - } - if (nextChar == ']') { - return; - } - x.back(); - break; - case ']': - return; - default: - throw x.syntaxError("Expected a ',' or ']'"); - } - } - } - } - - /** - * Construct a JSONArray from a source JSON text. - * - * @param source - * A string that begins with [ (left - * bracket) and ends with ] - *  (right bracket). - * @throws JSONException - * If there is a syntax error. - */ - public JSONArray(String source) throws JSONException { - this(new JSONTokener(source)); - } - - /** - * Construct a JSONArray from a Collection. - * - * @param collection - * A Collection. - */ - public JSONArray(Collection collection) { - if (collection == null) { - this.myArrayList = new ArrayList(); - } else { - this.myArrayList = new ArrayList(collection.size()); - for (Object o: collection){ - this.myArrayList.add(JSONObject.wrap(o)); - } - } - } - - /** - * Construct a JSONArray from an array - * - * @throws JSONException - * If not an array or if an array value is non-finite number. - */ - public JSONArray(Object array) throws JSONException { - this(); - if (array.getClass().isArray()) { - int length = Array.getLength(array); - this.myArrayList.ensureCapacity(length); - for (int i = 0; i < length; i += 1) { - this.put(JSONObject.wrap(Array.get(array, i))); - } - } else { - throw new JSONException( - "JSONArray initial value should be a string or collection or array."); - } - } - - @Override - public Iterator iterator() { - return this.myArrayList.iterator(); - } - - /** - * Get the object value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return An object value. - * @throws JSONException - * If there is no value for the index. - */ - public Object get(int index) throws JSONException { - Object object = this.opt(index); - if (object == null) { - throw new JSONException("JSONArray[" + index + "] not found."); - } - return object; - } - - /** - * Get the boolean value associated with an index. The string values "true" - * and "false" are converted to boolean. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The truth. - * @throws JSONException - * If there is no value for the index or if the value is not - * convertible to boolean. - */ - public boolean getBoolean(int index) throws JSONException { - Object object = this.get(index); - if (object.equals(Boolean.FALSE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("true"))) { - return true; - } - throw new JSONException("JSONArray[" + index + "] is not a boolean."); - } - - /** - * Get the double value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a number. - */ - public double getDouble(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number ? ((Number) object).doubleValue() - : Double.parseDouble((String) object); - } catch (Exception e) { - 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); - } - } - - /** - * Get the enum value associated with an index. - * - * @param clazz - * The type of enum to retrieve. - * @param index - * The index must be between 0 and length() - 1. - * @return The enum value at the index location - * @throws JSONException - * if the key is not found or if the value cannot be converted - * to an enum. - */ - public > E getEnum(Class clazz, int index) throws JSONException { - E val = optEnum(clazz, index); - if(val==null) { - // 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()) + "."); - } - return val; - } - - /** - * Get the BigDecimal value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a BigDecimal. - */ - public BigDecimal getBigDecimal (int index) throws JSONException { - Object object = this.get(index); - try { - return new BigDecimal(object.toString()); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] could not convert to BigDecimal.", e); - } - } - - /** - * Get the BigInteger value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a BigInteger. - */ - public BigInteger getBigInteger (int index) throws JSONException { - Object object = this.get(index); - try { - return new BigInteger(object.toString()); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] could not convert to BigInteger.", e); - } - } - - /** - * Get the int value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value is not a number. - */ - public int getInt(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number ? ((Number) object).intValue() - : Integer.parseInt((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number.", e); - } - } - - /** - * Get the JSONArray associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return A JSONArray value. - * @throws JSONException - * If there is no value for the index. or if the value is not a - * JSONArray - */ - public JSONArray getJSONArray(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONArray) { - return (JSONArray) object; - } - throw new JSONException("JSONArray[" + index + "] is not a JSONArray."); - } - - /** - * Get the JSONObject associated with an index. - * - * @param index - * subscript - * @return A JSONObject value. - * @throws JSONException - * If there is no value for the index or if the value is not a - * JSONObject - */ - public JSONObject getJSONObject(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONObject) { - return (JSONObject) object; - } - throw new JSONException("JSONArray[" + index + "] is not a JSONObject."); - } - - /** - * Get the long value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a number. - */ - public long getLong(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number ? ((Number) object).longValue() - : Long.parseLong((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number.", e); - } - } - - /** - * Get the string associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. - * @return A string value. - * @throws JSONException - * If there is no string value for the index. - */ - public String getString(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof String) { - return (String) object; - } - throw new JSONException("JSONArray[" + index + "] not a string."); - } - - /** - * Determine if the value is null. - * - * @param index - * The index must be between 0 and length() - 1. - * @return true if the value at the index is null, or if there is no value. - */ - public boolean isNull(int index) { - return JSONObject.NULL.equals(this.opt(index)); - } - - /** - * Make a string from the contents of this JSONArray. The - * separator string is inserted between each element. Warning: - * This method assumes that the data structure is acyclical. - * - * @param separator - * A string that will be inserted between the elements. - * @return a string. - * @throws JSONException - * If the array contains an invalid number. - */ - public String join(String separator) throws JSONException { - int len = this.length(); - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < len; i += 1) { - if (i > 0) { - sb.append(separator); - } - sb.append(JSONObject.valueToString(this.myArrayList.get(i))); - } - return sb.toString(); - } - - /** - * Get the number of elements in the JSONArray, included nulls. - * - * @return The length (or size). - */ - public int length() { - return this.myArrayList.size(); - } - - /** - * Get the optional object value associated with an index. - * - * @param index - * The index must be between 0 and length() - 1. If not, null is returned. - * @return An object value, or null if there is no object at that index. - */ - public Object opt(int index) { - return (index < 0 || index >= this.length()) ? null : this.myArrayList - .get(index); - } - - /** - * Get the optional boolean value associated with an index. It returns false - * if there is no value at that index, or if the value is not Boolean.TRUE - * or the String "true". - * - * @param index - * The index must be between 0 and length() - 1. - * @return The truth. - */ - public boolean optBoolean(int index) { - return this.optBoolean(index, false); - } - - /** - * Get the optional boolean value associated with an index. It returns the - * defaultValue if there is no value at that index or if it is not a Boolean - * or the String "true" or "false" (case insensitive). - * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * A boolean default. - * @return The truth. - */ - public boolean optBoolean(int index, boolean defaultValue) { - try { - return this.getBoolean(index); - } catch (Exception e) { - 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 index - * The index must be between 0 and length() - 1. - * @return The value. - */ - public double optDouble(int index) { - return this.optDouble(index, Double.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 index - * subscript - * @param defaultValue - * The default value. - * @return The value. - */ - public double optDouble(int index, double defaultValue) { - 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; - } - } + } + } + } + + /** + * Construct a JSONArray from a source JSON text. + * + * @param source + * A string that begins with [ (left + * bracket) and ends with ]  (right + * bracket). + * @throws JSONException + * If there is a syntax error. + */ + public JSONArray(String source) throws JSONException + { + this(new JSONTokener(source)); + } + + /** + * Construct a JSONArray from a Collection. + * + * @param collection + * A Collection. + */ + public JSONArray(Collection collection) + { + if (collection == null) + { + this.myArrayList = new ArrayList(); + } + else + { + this.myArrayList = new ArrayList(collection.size()); + for (Object o : collection) + { + this.myArrayList.add(JSONObject.wrap(o)); + } + } + } + + /** + * Construct a JSONArray from an array + * + * @throws JSONException + * If not an array or if an array value is non-finite number. + */ + public JSONArray(Object array) throws JSONException + { + this(); + if (array.getClass().isArray()) + { + int length = Array.getLength(array); + this.myArrayList.ensureCapacity(length); + for (int i = 0; i < length; i += 1) + { + this.put(JSONObject.wrap(Array.get(array, i))); + } + } + else + { + throw new JSONException( + "JSONArray initial value should be a string or collection or array."); + } + } + + @Override + public Iterator iterator() + { + return this.myArrayList.iterator(); + } + + /** + * Get the object value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return An object value. + * @throws JSONException + * If there is no value for the index. + */ + public Object get(int index) throws JSONException + { + Object object = this.opt(index); + if (object == null) + { + throw new JSONException("JSONArray[" + index + "] not found."); + } + return object; + } + + /** + * Get the boolean value associated with an index. The string values "true" + * and "false" are converted to boolean. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The truth. + * @throws JSONException + * If there is no value for the index or if the value is not + * convertible to boolean. + */ + public boolean getBoolean(int index) throws JSONException + { + Object object = this.get(index); + if (object.equals(Boolean.FALSE) || (object instanceof String + && ((String) object).equalsIgnoreCase("false"))) + { + return false; + } + else if (object.equals(Boolean.TRUE) || (object instanceof String + && ((String) object).equalsIgnoreCase("true"))) + { + return true; + } + throw new JSONException("JSONArray[" + index + "] is not a boolean."); + } + + /** + * Get the double value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted to a + * number. + */ + public double getDouble(int index) throws JSONException + { + Object object = this.get(index); + try + { + return object instanceof Number ? ((Number) object).doubleValue() + : Double.parseDouble((String) object); + } catch (Exception e) + { + 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); + } + } + + /** + * Get the enum value associated with an index. + * + * @param clazz + * The type of enum to retrieve. + * @param index + * The index must be between 0 and length() - 1. + * @return The enum value at the index location + * @throws JSONException + * if the key is not found or if the value cannot be converted to an + * enum. + */ + public > E getEnum(Class clazz, int index) + throws JSONException + { + E val = optEnum(clazz, index); + if (val == null) + { + // 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()) + "."); + } + return val; + } + + /** + * Get the BigDecimal value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted to a + * BigDecimal. + */ + public BigDecimal getBigDecimal(int index) throws JSONException + { + Object object = this.get(index); + try + { + return new BigDecimal(object.toString()); + } catch (Exception e) + { + throw new JSONException( + "JSONArray[" + index + "] could not convert to BigDecimal.", + e); + } + } + + /** + * Get the BigInteger value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted to a + * BigInteger. + */ + public BigInteger getBigInteger(int index) throws JSONException + { + Object object = this.get(index); + try + { + return new BigInteger(object.toString()); + } catch (Exception e) + { + throw new JSONException( + "JSONArray[" + index + "] could not convert to BigInteger.", + e); + } + } + + /** + * Get the int value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value is not a number. + */ + public int getInt(int index) throws JSONException + { + Object object = this.get(index); + try + { + return object instanceof Number ? ((Number) object).intValue() + : Integer.parseInt((String) object); + } catch (Exception e) + { + throw new JSONException("JSONArray[" + index + "] is not a number.", + e); + } + } + + /** + * Get the JSONArray associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A JSONArray value. + * @throws JSONException + * If there is no value for the index. or if the value is not a + * JSONArray + */ + public JSONArray getJSONArray(int index) throws JSONException + { + Object object = this.get(index); + if (object instanceof JSONArray) + { + return (JSONArray) object; + } + throw new JSONException("JSONArray[" + index + "] is not a JSONArray."); + } + + /** + * Get the JSONObject associated with an index. + * + * @param index + * subscript + * @return A JSONObject value. + * @throws JSONException + * If there is no value for the index or if the value is not a + * JSONObject + */ + public JSONObject getJSONObject(int index) throws JSONException + { + Object object = this.get(index); + if (object instanceof JSONObject) + { + return (JSONObject) object; + } + throw new JSONException( + "JSONArray[" + index + "] is not a JSONObject."); + } + + /** + * Get the long value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return The value. + * @throws JSONException + * If the key is not found or if the value cannot be converted to a + * number. + */ + public long getLong(int index) throws JSONException + { + Object object = this.get(index); + try + { + return object instanceof Number ? ((Number) object).longValue() + : Long.parseLong((String) object); + } catch (Exception e) + { + throw new JSONException("JSONArray[" + index + "] is not a number.", + e); + } + } + + /** + * Get the string associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A string value. + * @throws JSONException + * If there is no string value for the index. + */ + public String getString(int index) throws JSONException + { + Object object = this.get(index); + if (object instanceof String) + { + return (String) object; + } + throw new JSONException("JSONArray[" + index + "] not a string."); + } + + /** + * Determine if the value is null. + * + * @param index + * The index must be between 0 and length() - 1. + * @return true if the value at the index is null, or if there is + * no value. + */ + public boolean isNull(int index) + { + return JSONObject.NULL.equals(this.opt(index)); + } + + /** + * Make a string from the contents of this JSONArray. The + * separator string is inserted between each element. Warning: + * This method assumes that the data structure is acyclical. + * + * @param separator + * A string that will be inserted between the elements. + * @return a string. + * @throws JSONException + * If the array contains an invalid number. + */ + public String join(String separator) throws JSONException + { + int len = this.length(); + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < len; i += 1) + { + if (i > 0) + { + sb.append(separator); + } + sb.append(JSONObject.valueToString(this.myArrayList.get(i))); + } + return sb.toString(); + } + + /** + * Get the number of elements in the JSONArray, included nulls. + * + * @return The length (or size). + */ + public int length() + { + return this.myArrayList.size(); + } + + /** + * Get the optional object value associated with an index. + * + * @param index + * The index must be between 0 and length() - 1. If not, null is + * returned. + * @return An object value, or null if there is no object at that index. + */ + public Object opt(int index) + { + return (index < 0 || index >= this.length()) ? null + : this.myArrayList.get(index); + } + + /** + * Get the optional boolean value associated with an index. It returns false + * if there is no value at that index, or if the value is not Boolean.TRUE or + * the String "true". + * + * @param index + * The index must be between 0 and length() - 1. + * @return The truth. + */ + public boolean optBoolean(int index) + { + return this.optBoolean(index, false); + } + + /** + * Get the optional boolean value associated with an index. It returns the + * defaultValue if there is no value at that index or if it is not a Boolean + * or the String "true" or "false" (case insensitive). + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * A boolean default. + * @return The truth. + */ + public boolean optBoolean(int index, boolean defaultValue) + { + try + { + return this.getBoolean(index); + } catch (Exception e) + { + 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 index + * The index must be between 0 and length() - 1. + * @return The value. + */ + public double optDouble(int index) + { + return this.optDouble(index, Double.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 index + * subscript + * @param defaultValue + * The default value. + * @return The value. + */ + public double optDouble(int index, double defaultValue) + { + 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; - } - - /** - * 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; + } + + /** + * 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; - } - - /** - * Get the optional int value associated with an index. Zero 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 int optInt(int index) { - return this.optInt(index, 0); - } - - /** - * Get the optional int 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 - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. - * @return The value. - */ - public int optInt(int index, int defaultValue) { - 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; + } + + /** + * Get the optional int value associated with an index. Zero 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 int optInt(int index) + { + return this.optInt(index, 0); + } + + /** + * Get the optional int 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 + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @return The value. + */ + public int optInt(int index, int defaultValue) + { + 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; - } - - /** - * Get the enum value associated with a key. - * - * @param clazz - * The type of enum to retrieve. - * @param index - * The index must be between 0 and length() - 1. - * @return The enum value at the index location or null if not found - */ - public > E optEnum(Class clazz, int index) { - return this.optEnum(clazz, index, null); - } - - /** - * Get the enum value associated with a key. - * - * @param clazz - * The type of enum to retrieve. - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default in case the value is not found - * @return The enum value at the index location or defaultValue if - * the value is not found or cannot be assigned to clazz - */ - public > E optEnum(Class clazz, int index, E defaultValue) { - try { - Object val = this.opt(index); - if (JSONObject.NULL.equals(val)) { - return defaultValue; - } - if (clazz.isAssignableFrom(val.getClass())) { - // we just checked it! - @SuppressWarnings("unchecked") - E myE = (E) val; - return myE; - } - return Enum.valueOf(clazz, val.toString()); - } catch (IllegalArgumentException e) { - return defaultValue; - } catch (NullPointerException e) { - return defaultValue; - } - } - - - /** - * Get the optional BigInteger 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 - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. - * @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 { - final String valStr = val.toString(); - if(JSONObject.isDecimalNotation(valStr)) { - return new BigDecimal(valStr).toBigInteger(); - } - return new BigInteger(valStr); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get the optional BigDecimal 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 - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. - * @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 new BigDecimal(val.toString()); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * Get the optional JSONArray associated with an index. - * - * @param index - * subscript - * @return A JSONArray value, or null if the index has no value, or if the - * value is not a JSONArray. - */ - public JSONArray optJSONArray(int index) { - Object o = this.opt(index); - return o instanceof JSONArray ? (JSONArray) o : null; - } - - /** - * Get the optional JSONObject associated with an index. Null is returned if - * the key is not found, or null if the index has no value, or if the value - * is not a JSONObject. - * - * @param index - * The index must be between 0 and length() - 1. - * @return A JSONObject value. - */ - public JSONObject optJSONObject(int index) { - Object o = this.opt(index); - return o instanceof JSONObject ? (JSONObject) o : null; - } - - /** - * Get the optional long value associated with an index. Zero 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 long optLong(int index) { - return this.optLong(index, 0); - } - - /** - * Get the optional long 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 - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. - * @return The value. - */ - public long optLong(int index, long defaultValue) { - 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 the enum value associated with a key. + * + * @param clazz + * The type of enum to retrieve. + * @param index + * The index must be between 0 and length() - 1. + * @return The enum value at the index location or null if not found + */ + public > E optEnum(Class clazz, int index) + { + return this.optEnum(clazz, index, null); + } + + /** + * Get the enum value associated with a key. + * + * @param clazz + * The type of enum to retrieve. + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default in case the value is not found + * @return The enum value at the index location or defaultValue if the value + * is not found or cannot be assigned to clazz + */ + public > E optEnum(Class clazz, int index, + E defaultValue) + { + try + { + Object val = this.opt(index); + if (JSONObject.NULL.equals(val)) + { return defaultValue; - } - - /** - * Get an optional {@link Number} value associated with a key, or null - * 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; - } - } + } + if (clazz.isAssignableFrom(val.getClass())) + { + // we just checked it! + @SuppressWarnings("unchecked") + E myE = (E) val; + return myE; + } + return Enum.valueOf(clazz, val.toString()); + } catch (IllegalArgumentException e) + { + return defaultValue; + } catch (NullPointerException e) + { + return defaultValue; + } + } + + /** + * Get the optional BigInteger 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 + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @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 + { + final String valStr = val.toString(); + if (JSONObject.isDecimalNotation(valStr)) + { + return new BigDecimal(valStr).toBigInteger(); + } + return new BigInteger(valStr); + } catch (Exception e) + { + return defaultValue; + } + } + + /** + * Get the optional BigDecimal 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 + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @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 new BigDecimal(val.toString()); + } catch (Exception e) + { + return defaultValue; + } + } + + /** + * Get the optional JSONArray associated with an index. + * + * @param index + * subscript + * @return A JSONArray value, or null if the index has no value, or if the + * value is not a JSONArray. + */ + public JSONArray optJSONArray(int index) + { + Object o = this.opt(index); + return o instanceof JSONArray ? (JSONArray) o : null; + } + + /** + * Get the optional JSONObject associated with an index. Null is returned if + * the key is not found, or null if the index has no value, or if the value is + * not a JSONObject. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A JSONObject value. + */ + public JSONObject optJSONObject(int index) + { + Object o = this.opt(index); + return o instanceof JSONObject ? (JSONObject) o : null; + } + + /** + * Get the optional long value associated with an index. Zero 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 long optLong(int index) + { + return this.optLong(index, 0); + } + + /** + * Get the optional long 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 + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @return The value. + */ + public long optLong(int index, long defaultValue) + { + 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; - } - - /** - * 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 converted to a string. - * - * @param index - * The index must be between 0 and length() - 1. - * @return A String value. - */ - public String optString(int index) { - return this.optString(index, ""); - } - - /** - * Get the optional string associated with an index. The defaultValue is - * returned if the key is not found. - * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. - * @return A String value. - */ - public String optString(int index, String defaultValue) { - Object object = this.opt(index); - return JSONObject.NULL.equals(object) ? defaultValue : object - .toString(); - } - - /** - * Append a boolean value. This increases the array's length by one. - * - * @param value - * A boolean value. - * @return this. - */ - public JSONArray put(boolean value) { - return this.put(value ? Boolean.TRUE : Boolean.FALSE); - } - - /** - * Put a value in the JSONArray, where the value will be a JSONArray which - * is produced from a Collection. - * - * @param value - * A Collection value. - * @return this. - * @throws JSONException - * If the value is non-finite number. - */ - public JSONArray put(Collection value) { - return this.put(new JSONArray(value)); - } - - /** - * Append a double value. This increases the array's length by one. - * - * @param value - * A double value. - * @return this. - * @throws JSONException - * if the value is not finite. - */ - public JSONArray put(double value) throws JSONException { - return this.put(Double.valueOf(value)); - } - - /** - * Append a float value. This increases the array's length by one. - * - * @param value - * A float value. - * @return this. - * @throws JSONException - * if the value is not finite. - */ - public JSONArray put(float value) throws JSONException { - return this.put(Float.valueOf(value)); - } - - /** - * Append an int value. This increases the array's length by one. - * - * @param value - * An int value. - * @return this. - */ - public JSONArray put(int value) { - return this.put(Integer.valueOf(value)); - } - - /** - * Append an long value. This increases the array's length by one. - * - * @param value - * A long value. - * @return this. - */ - public JSONArray put(long value) { - return this.put(Long.valueOf(value)); - } - - /** - * Put a value in the JSONArray, where the value will be a JSONObject which - * is produced from a Map. - * - * @param value - * A Map value. - * @return this. - * @throws JSONException - * If a value in the map is non-finite number. - * @throws NullPointerException - * If a key in the map is null - */ - public JSONArray put(Map value) { - return this.put(new JSONObject(value)); - } - - /** - * Append an object value. This increases the array's length by one. - * - * @param value - * An object value. The value should be a Boolean, Double, - * Integer, JSONArray, JSONObject, Long, or String, or the - * JSONObject.NULL object. - * @return this. - * @throws JSONException - * If the value is non-finite number. - */ - public JSONArray put(Object value) { - JSONObject.testValidity(value); - this.myArrayList.add(value); - return this; - } - - /** - * Put or replace a boolean value in the JSONArray. If the index is greater - * than the length of the JSONArray, then null elements will be added as - * necessary to pad it out. - * - * @param index - * The subscript. - * @param value - * A boolean value. - * @return this. - * @throws JSONException - * If the index is negative. - */ - public JSONArray put(int index, boolean value) throws JSONException { - return this.put(index, value ? Boolean.TRUE : Boolean.FALSE); - } - - /** - * Put a value in the JSONArray, where the value will be a JSONArray which - * is produced from a Collection. - * - * @param index - * The subscript. - * @param value - * A Collection value. - * @return this. - * @throws JSONException - * If the index is negative or if the value is non-finite. - */ - public JSONArray put(int index, Collection value) throws JSONException { - return this.put(index, new JSONArray(value)); - } - - /** - * Put or replace a double value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad it - * out. - * - * @param index - * The subscript. - * @param value - * A double value. - * @return this. - * @throws JSONException - * If the index is negative or if the value is non-finite. - */ - public JSONArray put(int index, double value) throws JSONException { - return this.put(index, Double.valueOf(value)); - } - - /** - * Put or replace a float value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad it - * out. - * - * @param index - * The subscript. - * @param value - * A float value. - * @return this. - * @throws JSONException - * If the index is negative or if the value is non-finite. - */ - public JSONArray put(int index, float value) throws JSONException { - return this.put(index, Float.valueOf(value)); - } - - /** - * Put or replace an int value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad it - * out. - * - * @param index - * The subscript. - * @param value - * An int value. - * @return this. - * @throws JSONException - * If the index is negative. - */ - public JSONArray put(int index, int value) throws JSONException { - return this.put(index, Integer.valueOf(value)); - } - - /** - * Put or replace a long value. If the index is greater than the length of - * the JSONArray, then null elements will be added as necessary to pad it - * out. - * - * @param index - * The subscript. - * @param value - * A long value. - * @return this. - * @throws JSONException - * If the index is negative. - */ - public JSONArray put(int index, long value) throws JSONException { - return this.put(index, Long.valueOf(value)); - } - - /** - * Put a value in the JSONArray, where the value will be a JSONObject that - * is produced from a Map. - * - * @param index - * The subscript. - * @param value - * The Map value. - * @return this. - * @throws JSONException - * If the index is negative or if the the value is an invalid - * number. - * @throws NullPointerException - * If a key in the map is null - */ - public JSONArray put(int index, Map value) throws JSONException { - this.put(index, new JSONObject(value)); - return this; - } - - /** - * Put or replace an object value in the JSONArray. If the index is greater - * than the length of the JSONArray, then null elements will be added as - * necessary to pad it out. - * - * @param index - * The subscript. - * @param value - * The value to put into the array. The value should be a - * Boolean, Double, Integer, JSONArray, JSONObject, Long, or - * String, or the JSONObject.NULL object. - * @return this. - * @throws JSONException - * If the index is negative or if the the value is an invalid - * number. - */ - public JSONArray put(int index, Object value) throws JSONException { - if (index < 0) { - throw new JSONException("JSONArray[" + index + "] not found."); - } - if (index < this.length()) { - JSONObject.testValidity(value); - this.myArrayList.set(index, value); - return this; - } - if(index == this.length()){ - // simple append - return this.put(value); - } - // if we are inserting past the length, we want to grow the array all at once - // instead of incrementally. - this.myArrayList.ensureCapacity(index + 1); - while (index != this.length()) { - // we don't need to test validity of NULL objects - this.myArrayList.add(JSONObject.NULL); - } - return this.put(value); - } - - /** - * Creates a JSONPointer using an initialization string and tries to - * match it to an item within this JSONArray. For example, given a - * JSONArray initialized with this document: - *
    -     * [
    -     *     {"b":"c"}
    -     * ]
    -     * 
    - * and this JSONPointer string: - *
    -     * "/0/b"
    -     * 
    - * Then this method will return the String "c" - * A JSONPointerException may be thrown from code called by this method. - * - * @param jsonPointer string that can be used to create a JSONPointer - * @return the item matched by the JSONPointer, otherwise null - */ - public Object query(String jsonPointer) { - return query(new JSONPointer(jsonPointer)); - } - - /** - * Uses a uaer initialized JSONPointer and tries to - * match it to an item whithin this JSONArray. For example, given a - * JSONArray initialized with this document: - *
    -     * [
    -     *     {"b":"c"}
    -     * ]
    -     * 
    - * and this JSONPointer: - *
    -     * "/0/b"
    -     * 
    - * Then this method will return the String "c" - * A JSONPointerException may be thrown from code called by this method. - * - * @param jsonPointer string that can be used to create a JSONPointer - * @return the item matched by the JSONPointer, otherwise null - */ - public Object query(JSONPointer jsonPointer) { - return jsonPointer.queryFrom(this); - } - - /** - * Queries and returns a value from this object using {@code jsonPointer}, or - * returns null if the query fails due to a missing key. - * - * @param jsonPointer the string representation of the JSON pointer - * @return the queried value or {@code null} - * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax - */ - public Object optQuery(String jsonPointer) { - return optQuery(new JSONPointer(jsonPointer)); - } - - /** - * Queries and returns a value from this object using {@code jsonPointer}, or - * returns null if the query fails due to a missing key. - * - * @param jsonPointer The JSON pointer - * @return the queried value or {@code null} - * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax - */ - public Object optQuery(JSONPointer jsonPointer) { - try { - return jsonPointer.queryFrom(this); - } catch (JSONPointerException e) { - return null; - } - } - - /** - * Remove an index and close the hole. - * - * @param index - * The index of the element to be removed. - * @return The value that was associated with the index, or null if there - * was no value. - */ - public Object remove(int index) { - return index >= 0 && index < this.length() + } + } + return defaultValue; + } + + /** + * Get an optional {@link Number} value associated with a key, or + * null 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 converted to a string. + * + * @param index + * The index must be between 0 and length() - 1. + * @return A String value. + */ + public String optString(int index) + { + return this.optString(index, ""); + } + + /** + * Get the optional string associated with an index. The defaultValue is + * returned if the key is not found. + * + * @param index + * The index must be between 0 and length() - 1. + * @param defaultValue + * The default value. + * @return A String value. + */ + public String optString(int index, String defaultValue) + { + Object object = this.opt(index); + return JSONObject.NULL.equals(object) ? defaultValue + : object.toString(); + } + + /** + * Append a boolean value. This increases the array's length by one. + * + * @param value + * A boolean value. + * @return this. + */ + public JSONArray put(boolean value) + { + return this.put(value ? Boolean.TRUE : Boolean.FALSE); + } + + /** + * Put a value in the JSONArray, where the value will be a JSONArray which is + * produced from a Collection. + * + * @param value + * A Collection value. + * @return this. + * @throws JSONException + * If the value is non-finite number. + */ + public JSONArray put(Collection value) + { + return this.put(new JSONArray(value)); + } + + /** + * Append a double value. This increases the array's length by one. + * + * @param value + * A double value. + * @return this. + * @throws JSONException + * if the value is not finite. + */ + public JSONArray put(double value) throws JSONException + { + return this.put(Double.valueOf(value)); + } + + /** + * Append a float value. This increases the array's length by one. + * + * @param value + * A float value. + * @return this. + * @throws JSONException + * if the value is not finite. + */ + public JSONArray put(float value) throws JSONException + { + return this.put(Float.valueOf(value)); + } + + /** + * Append an int value. This increases the array's length by one. + * + * @param value + * An int value. + * @return this. + */ + public JSONArray put(int value) + { + return this.put(Integer.valueOf(value)); + } + + /** + * Append an long value. This increases the array's length by one. + * + * @param value + * A long value. + * @return this. + */ + public JSONArray put(long value) + { + return this.put(Long.valueOf(value)); + } + + /** + * Put a value in the JSONArray, where the value will be a JSONObject which is + * produced from a Map. + * + * @param value + * A Map value. + * @return this. + * @throws JSONException + * If a value in the map is non-finite number. + * @throws NullPointerException + * If a key in the map is null + */ + public JSONArray put(Map value) + { + return this.put(new JSONObject(value)); + } + + /** + * Append an object value. This increases the array's length by one. + * + * @param value + * An object value. The value should be a Boolean, Double, Integer, + * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL + * object. + * @return this. + * @throws JSONException + * If the value is non-finite number. + */ + public JSONArray put(Object value) + { + JSONObject.testValidity(value); + this.myArrayList.add(value); + return this; + } + + /** + * Put or replace a boolean value in the JSONArray. If the index is greater + * than the length of the JSONArray, then null elements will be added as + * necessary to pad it out. + * + * @param index + * The subscript. + * @param value + * A boolean value. + * @return this. + * @throws JSONException + * If the index is negative. + */ + public JSONArray put(int index, boolean value) throws JSONException + { + return this.put(index, value ? Boolean.TRUE : Boolean.FALSE); + } + + /** + * Put a value in the JSONArray, where the value will be a JSONArray which is + * produced from a Collection. + * + * @param index + * The subscript. + * @param value + * A Collection value. + * @return this. + * @throws JSONException + * If the index is negative or if the value is non-finite. + */ + public JSONArray put(int index, Collection value) throws JSONException + { + return this.put(index, new JSONArray(value)); + } + + /** + * Put or replace a double value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad it out. + * + * @param index + * The subscript. + * @param value + * A double value. + * @return this. + * @throws JSONException + * If the index is negative or if the value is non-finite. + */ + public JSONArray put(int index, double value) throws JSONException + { + return this.put(index, Double.valueOf(value)); + } + + /** + * Put or replace a float value. If the index is greater than the length of + * the JSONArray, then null elements will be added as necessary to pad it out. + * + * @param index + * The subscript. + * @param value + * A float value. + * @return this. + * @throws JSONException + * If the index is negative or if the value is non-finite. + */ + public JSONArray put(int index, float value) throws JSONException + { + return this.put(index, Float.valueOf(value)); + } + + /** + * Put or replace an int value. If the index is greater than the length of the + * JSONArray, then null elements will be added as necessary to pad it out. + * + * @param index + * The subscript. + * @param value + * An int value. + * @return this. + * @throws JSONException + * If the index is negative. + */ + public JSONArray put(int index, int value) throws JSONException + { + return this.put(index, Integer.valueOf(value)); + } + + /** + * Put or replace a long value. If the index is greater than the length of the + * JSONArray, then null elements will be added as necessary to pad it out. + * + * @param index + * The subscript. + * @param value + * A long value. + * @return this. + * @throws JSONException + * If the index is negative. + */ + public JSONArray put(int index, long value) throws JSONException + { + return this.put(index, Long.valueOf(value)); + } + + /** + * Put a value in the JSONArray, where the value will be a JSONObject that is + * produced from a Map. + * + * @param index + * The subscript. + * @param value + * The Map value. + * @return this. + * @throws JSONException + * If the index is negative or if the the value is an invalid + * number. + * @throws NullPointerException + * If a key in the map is null + */ + public JSONArray put(int index, Map value) throws JSONException + { + this.put(index, new JSONObject(value)); + return this; + } + + /** + * Put or replace an object value in the JSONArray. If the index is greater + * than the length of the JSONArray, then null elements will be added as + * necessary to pad it out. + * + * @param index + * The subscript. + * @param value + * The value to put into the array. The value should be a Boolean, + * Double, Integer, JSONArray, JSONObject, Long, or String, or the + * JSONObject.NULL object. + * @return this. + * @throws JSONException + * If the index is negative or if the the value is an invalid + * number. + */ + public JSONArray put(int index, Object value) throws JSONException + { + if (index < 0) + { + throw new JSONException("JSONArray[" + index + "] not found."); + } + if (index < this.length()) + { + JSONObject.testValidity(value); + this.myArrayList.set(index, value); + return this; + } + if (index == this.length()) + { + // simple append + return this.put(value); + } + // if we are inserting past the length, we want to grow the array all at + // once + // instead of incrementally. + this.myArrayList.ensureCapacity(index + 1); + while (index != this.length()) + { + // we don't need to test validity of NULL objects + this.myArrayList.add(JSONObject.NULL); + } + return this.put(value); + } + + /** + * Creates a JSONPointer using an initialization string and tries to match it + * to an item within this JSONArray. For example, given a JSONArray + * initialized with this document: + * + *
    +   * [
    +   *     {"b":"c"}
    +   * ]
    +   * 
    + * + * and this JSONPointer string: + * + *
    +   * "/0/b"
    +   * 
    + * + * Then this method will return the String "c" A JSONPointerException may be + * thrown from code called by this method. + * + * @param jsonPointer + * string that can be used to create a JSONPointer + * @return the item matched by the JSONPointer, otherwise null + */ + public Object query(String jsonPointer) + { + return query(new JSONPointer(jsonPointer)); + } + + /** + * Uses a uaer initialized JSONPointer and tries to match it to an item + * whithin this JSONArray. For example, given a JSONArray initialized with + * this document: + * + *
    +   * [
    +   *     {"b":"c"}
    +   * ]
    +   * 
    + * + * and this JSONPointer: + * + *
    +   * "/0/b"
    +   * 
    + * + * Then this method will return the String "c" A JSONPointerException may be + * thrown from code called by this method. + * + * @param jsonPointer + * string that can be used to create a JSONPointer + * @return the item matched by the JSONPointer, otherwise null + */ + public Object query(JSONPointer jsonPointer) + { + return jsonPointer.queryFrom(this); + } + + /** + * Queries and returns a value from this object using {@code jsonPointer}, or + * returns null if the query fails due to a missing key. + * + * @param jsonPointer + * the string representation of the JSON pointer + * @return the queried value or {@code null} + * @throws IllegalArgumentException + * if {@code jsonPointer} has invalid syntax + */ + public Object optQuery(String jsonPointer) + { + return optQuery(new JSONPointer(jsonPointer)); + } + + /** + * Queries and returns a value from this object using {@code jsonPointer}, or + * returns null if the query fails due to a missing key. + * + * @param jsonPointer + * The JSON pointer + * @return the queried value or {@code null} + * @throws IllegalArgumentException + * if {@code jsonPointer} has invalid syntax + */ + public Object optQuery(JSONPointer jsonPointer) + { + try + { + return jsonPointer.queryFrom(this); + } catch (JSONPointerException e) + { + return null; + } + } + + /** + * Remove an index and close the hole. + * + * @param index + * The index of the element to be removed. + * @return The value that was associated with the index, or null if there was + * no value. + */ + public Object remove(int index) + { + return index >= 0 && index < this.length() ? this.myArrayList.remove(index) : null; - } - - /** - * Determine if two JSONArrays are similar. - * They must contain similar sequences. - * - * @param other The other JSONArray - * @return true if they are equal - */ - public boolean similar(Object other) { - if (!(other instanceof JSONArray)) { - return false; + } + + /** + * Determine if two JSONArrays are similar. They must contain similar + * sequences. + * + * @param other + * The other JSONArray + * @return true if they are equal + */ + public boolean similar(Object other) + { + if (!(other instanceof JSONArray)) + { + return false; + } + int len = this.length(); + if (len != ((JSONArray) other).length()) + { + return false; + } + for (int i = 0; i < len; i += 1) + { + Object valueThis = this.myArrayList.get(i); + Object valueOther = ((JSONArray) other).myArrayList.get(i); + if (valueThis == valueOther) + { + continue; + } + if (valueThis == null) + { + return false; + } + if (valueThis instanceof JSONObject) + { + if (!((JSONObject) valueThis).similar(valueOther)) + { + return false; } - int len = this.length(); - if (len != ((JSONArray)other).length()) { - return false; + } + else if (valueThis instanceof JSONArray) + { + if (!((JSONArray) valueThis).similar(valueOther)) + { + return false; } - for (int i = 0; i < len; i += 1) { - Object valueThis = this.myArrayList.get(i); - Object valueOther = ((JSONArray)other).myArrayList.get(i); - if(valueThis == valueOther) { - continue; - } - if(valueThis == null) { - return false; - } - if (valueThis instanceof JSONObject) { - if (!((JSONObject)valueThis).similar(valueOther)) { - return false; - } - } else if (valueThis instanceof JSONArray) { - if (!((JSONArray)valueThis).similar(valueOther)) { - return false; - } - } else if (!valueThis.equals(valueOther)) { - return false; - } + } + else if (!valueThis.equals(valueOther)) + { + return false; + } + } + return true; + } + + /** + * Produce a JSONObject by combining a JSONArray of names with the values of + * this JSONArray. + * + * @param names + * A JSONArray containing a list of key strings. These will be paired + * with the values. + * @return A JSONObject, or null if there are no names or if this JSONArray + * has no values. + * @throws JSONException + * If any of the names are null. + */ + public JSONObject toJSONObject(JSONArray names) throws JSONException + { + if (names == null || names.isEmpty() || this.isEmpty()) + { + return null; + } + JSONObject jo = new JSONObject(names.length()); + for (int i = 0; i < names.length(); i += 1) + { + jo.put(names.getString(i), this.opt(i)); + } + return jo; + } + + /** + * Make a JSON text of this JSONArray. For compactness, no unnecessary + * whitespace is added. If it is not possible to produce a syntactically + * correct JSON text then null will be returned instead. This could occur if + * the array contains an invalid number. + *

    + * Warning: This method assumes that the data structure is acyclical. + * + * @return a printable, displayable, transmittable representation of the + * array. + */ + @Override + public String toString() + { + try + { + return this.toString(0); + } catch (Exception e) + { + return null; + } + } + + /** + * Make a pretty-printed JSON text of this JSONArray. + * + *

    + * If indentFactor > 0 and the {@link JSONArray} has only one + * element, then the array will be output on a single line: + * + *

    +   * {@code [1]}
    +   * 
    + * + *

    + * If an array has 2 or more elements, then it will be output across multiple + * lines: + * + *

    +   * {@code
    +   * [
    +   * 1,
    +   * "value 2",
    +   * 3
    +   * ]
    +   * }
    +   * 
    + *

    + * Warning: This method assumes that the data structure is acyclical. + * + * @param indentFactor + * The number of spaces to add to each level of indentation. + * @return a printable, displayable, transmittable representation of the + * object, beginning with [ (left + * bracket) and ending with ]  (right + * bracket). + * @throws JSONException + */ + public String toString(int indentFactor) throws JSONException + { + StringWriter sw = new StringWriter(); + synchronized (sw.getBuffer()) + { + return this.write(sw, indentFactor, 0).toString(); + } + } + + /** + * Write the contents of the JSONArray as JSON text to a writer. For + * compactness, no whitespace is added. + *

    + * Warning: This method assumes that the data structure is acyclical. + * + * @return The writer. + * @throws JSONException + */ + public Writer write(Writer writer) throws JSONException + { + return this.write(writer, 0, 0); + } + + /** + * Write the contents of the JSONArray as JSON text to a writer. + * + *

    + * If indentFactor > 0 and the {@link JSONArray} has only one + * element, then the array will be output on a single line: + * + *

    +   * {@code [1]}
    +   * 
    + * + *

    + * If an array has 2 or more elements, then it will be output across multiple + * lines: + * + *

    +   * {@code
    +   * [
    +   * 1,
    +   * "value 2",
    +   * 3
    +   * ]
    +   * }
    +   * 
    + *

    + * Warning: This method assumes that the data structure is acyclical. + * + * @param writer + * Writes the serialized JSON + * @param indentFactor + * The number of spaces to add to each level of indentation. + * @param indent + * The indentation of the top level. + * @return The writer. + * @throws JSONException + */ + public Writer write(Writer writer, int indentFactor, int indent) + throws JSONException + { + try + { + boolean commanate = false; + int length = this.length(); + writer.write('['); + + if (length == 1) + { + try + { + JSONObject.writeValue(writer, this.myArrayList.get(0), + indentFactor, indent); + } catch (Exception e) + { + throw new JSONException( + "Unable to write JSONArray value at index: 0", e); } - return true; - } - - /** - * Produce a JSONObject by combining a JSONArray of names with the values of - * this JSONArray. - * - * @param names - * A JSONArray containing a list of key strings. These will be - * paired with the values. - * @return A JSONObject, or null if there are no names or if this JSONArray - * has no values. - * @throws JSONException - * If any of the names are null. - */ - public JSONObject toJSONObject(JSONArray names) throws JSONException { - if (names == null || names.isEmpty() || this.isEmpty()) { - return null; - } - JSONObject jo = new JSONObject(names.length()); - for (int i = 0; i < names.length(); i += 1) { - jo.put(names.getString(i), this.opt(i)); - } - return jo; - } - - /** - * Make a JSON text of this JSONArray. For compactness, no unnecessary - * whitespace is added. If it is not possible to produce a syntactically - * correct JSON text then null will be returned instead. This could occur if - * the array contains an invalid number. - *

    - * Warning: This method assumes that the data structure is acyclical. - * - * - * @return a printable, displayable, transmittable representation of the - * array. - */ - @Override - public String toString() { - try { - return this.toString(0); - } catch (Exception e) { - return null; - } - } - - /** - * Make a pretty-printed JSON text of this JSONArray. - * - *

    If indentFactor > 0 and the {@link JSONArray} has only - * one element, then the array will be output on a single line: - *

    {@code [1]}
    - * - *

    If an array has 2 or more elements, then it will be output across - * multiple lines:

    {@code
    -     * [
    -     * 1,
    -     * "value 2",
    -     * 3
    -     * ]
    -     * }
    - *

    - * Warning: This method assumes that the data structure is acyclical. - * - * - * @param indentFactor - * The number of spaces to add to each level of indentation. - * @return a printable, displayable, transmittable representation of the - * object, beginning with [ (left - * bracket) and ending with ] - *  (right bracket). - * @throws JSONException - */ - public String toString(int indentFactor) throws JSONException { - StringWriter sw = new StringWriter(); - synchronized (sw.getBuffer()) { - return this.write(sw, indentFactor, 0).toString(); - } - } - - /** - * Write the contents of the JSONArray as JSON text to a writer. For - * compactness, no whitespace is added. - *

    - * Warning: This method assumes that the data structure is acyclical. - * - * - * @return The writer. - * @throws JSONException - */ - public Writer write(Writer writer) throws JSONException { - return this.write(writer, 0, 0); - } - - /** - * Write the contents of the JSONArray as JSON text to a writer. - * - *

    If indentFactor > 0 and the {@link JSONArray} has only - * one element, then the array will be output on a single line: - *

    {@code [1]}
    - * - *

    If an array has 2 or more elements, then it will be output across - * multiple lines:

    {@code
    -     * [
    -     * 1,
    -     * "value 2",
    -     * 3
    -     * ]
    -     * }
    - *

    - * Warning: This method assumes that the data structure is acyclical. - * - * - * @param writer - * Writes the serialized JSON - * @param indentFactor - * The number of spaces to add to each level of indentation. - * @param indent - * The indentation of the top level. - * @return The writer. - * @throws JSONException - */ - public Writer write(Writer writer, int indentFactor, int indent) - throws JSONException { - try { - boolean commanate = false; - int length = this.length(); - writer.write('['); - - if (length == 1) { - try { - JSONObject.writeValue(writer, this.myArrayList.get(0), - indentFactor, indent); - } catch (Exception e) { - throw new JSONException("Unable to write JSONArray value at index: 0", e); - } - } else if (length != 0) { - final int newindent = indent + indentFactor; - - for (int i = 0; i < length; i += 1) { - if (commanate) { - writer.write(','); - } - if (indentFactor > 0) { - writer.write('\n'); - } - JSONObject.indent(writer, newindent); - try { - JSONObject.writeValue(writer, this.myArrayList.get(i), - indentFactor, newindent); - } catch (Exception e) { - throw new JSONException("Unable to write JSONArray value at index: " + i, e); - } - commanate = true; - } - if (indentFactor > 0) { - writer.write('\n'); - } - JSONObject.indent(writer, indent); - } - writer.write(']'); - return writer; - } catch (IOException e) { - throw new JSONException(e); + } + else if (length != 0) + { + final int newindent = indent + indentFactor; + + for (int i = 0; i < length; i += 1) + { + if (commanate) + { + writer.write(','); + } + if (indentFactor > 0) + { + writer.write('\n'); + } + JSONObject.indent(writer, newindent); + try + { + JSONObject.writeValue(writer, this.myArrayList.get(i), + indentFactor, newindent); + } catch (Exception e) + { + throw new JSONException( + "Unable to write JSONArray value at index: " + i, e); + } + commanate = true; } - } - - /** - * Returns a java.util.List containing all of the elements in this array. - * If an element in the array is a JSONArray or JSONObject it will also - * be converted. - *

    - * Warning: This method assumes that the data structure is acyclical. - * - * @return a java.util.List containing the elements of this array - */ - public List toList() { - List results = new ArrayList(this.myArrayList.size()); - for (Object element : this.myArrayList) { - if (element == null || JSONObject.NULL.equals(element)) { - results.add(null); - } else if (element instanceof JSONArray) { - results.add(((JSONArray) element).toList()); - } else if (element instanceof JSONObject) { - results.add(((JSONObject) element).toMap()); - } else { - results.add(element); - } + if (indentFactor > 0) + { + writer.write('\n'); } - return results; - } - - /** - * Check if JSONArray is empty. - * - * @return true if JSONArray is empty, otherwise false. - */ - public boolean isEmpty() { - return myArrayList.isEmpty(); - } + JSONObject.indent(writer, indent); + } + writer.write(']'); + return writer; + } catch (IOException e) + { + throw new JSONException(e); + } + } + + /** + * Returns a java.util.List containing all of the elements in this array. If + * an element in the array is a JSONArray or JSONObject it will also be + * converted. + *

    + * Warning: This method assumes that the data structure is acyclical. + * + * @return a java.util.List containing the elements of this array + */ + public List toList() + { + List results = new ArrayList(this.myArrayList.size()); + for (Object element : this.myArrayList) + { + if (element == null || JSONObject.NULL.equals(element)) + { + results.add(null); + } + else if (element instanceof JSONArray) + { + results.add(((JSONArray) element).toList()); + } + else if (element instanceof JSONObject) + { + results.add(((JSONObject) element).toMap()); + } + else + { + results.add(element); + } + } + return results; + } + + /** + * Check if JSONArray is empty. + * + * @return true if JSONArray is empty, otherwise false. + */ + public boolean isEmpty() + { + return myArrayList.isEmpty(); + } }