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 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;
}
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;
}
}
else if (valueThis instanceof JSONArray)
{
if (!((JSONArray) valueThis).similar(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);
}
}
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);
}
}
/**
* 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();
}
}