pax_global_header 0000666 0000000 0000000 00000000064 12071360135 0014510 g ustar 00root root 0000000 0000000 52 comment=34468a2cd4c6987eee38240e87e144825dfda7cb
libandroid-json-org-java-20121204-20090211/ 0000775 0000000 0000000 00000000000 12071360135 0017423 5 ustar 00root root 0000000 0000000 libandroid-json-org-java-20121204-20090211/src/ 0000775 0000000 0000000 00000000000 12071360135 0020212 5 ustar 00root root 0000000 0000000 libandroid-json-org-java-20121204-20090211/src/main/ 0000775 0000000 0000000 00000000000 12071360135 0021136 5 ustar 00root root 0000000 0000000 libandroid-json-org-java-20121204-20090211/src/main/java/ 0000775 0000000 0000000 00000000000 12071360135 0022057 5 ustar 00root root 0000000 0000000 libandroid-json-org-java-20121204-20090211/src/main/java/org/ 0000775 0000000 0000000 00000000000 12071360135 0022646 5 ustar 00root root 0000000 0000000 libandroid-json-org-java-20121204-20090211/src/main/java/org/json/ 0000775 0000000 0000000 00000000000 12071360135 0023617 5 ustar 00root root 0000000 0000000 libandroid-json-org-java-20121204-20090211/src/main/java/org/json/JSON.java 0000664 0000000 0000000 00000007454 12071360135 0025245 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.json;
class JSON {
/**
* Returns the input if it is a JSON-permissible value; throws otherwise.
*/
static double checkDouble(double d) throws JSONException {
if (Double.isInfinite(d) || Double.isNaN(d)) {
throw new JSONException("Forbidden numeric value: " + d);
}
return d;
}
static Boolean toBoolean(Object value) {
if (value instanceof Boolean) {
return (Boolean) value;
} else if (value instanceof String) {
String stringValue = (String) value;
if ("true".equalsIgnoreCase(stringValue)) {
return true;
} else if ("false".equalsIgnoreCase(stringValue)) {
return false;
}
}
return null;
}
static Double toDouble(Object value) {
if (value instanceof Double) {
return (Double) value;
} else if (value instanceof Number) {
return ((Number) value).doubleValue();
} else if (value instanceof String) {
try {
return Double.valueOf((String) value);
} catch (NumberFormatException ignored) {
}
}
return null;
}
static Integer toInteger(Object value) {
if (value instanceof Integer) {
return (Integer) value;
} else if (value instanceof Number) {
return ((Number) value).intValue();
} else if (value instanceof String) {
try {
return (int) Double.parseDouble((String) value);
} catch (NumberFormatException ignored) {
}
}
return null;
}
static Long toLong(Object value) {
if (value instanceof Long) {
return (Long) value;
} else if (value instanceof Number) {
return ((Number) value).longValue();
} else if (value instanceof String) {
try {
return (long) Double.parseDouble((String) value);
} catch (NumberFormatException ignored) {
}
}
return null;
}
static String toString(Object value) {
if (value instanceof String) {
return (String) value;
} else if (value != null) {
return String.valueOf(value);
}
return null;
}
public static JSONException typeMismatch(Object indexOrName, Object actual,
String requiredType) throws JSONException {
if (actual == null) {
throw new JSONException("Value at " + indexOrName + " is null.");
} else {
throw new JSONException("Value " + actual + " at " + indexOrName
+ " of type " + actual.getClass().getName()
+ " cannot be converted to " + requiredType);
}
}
public static JSONException typeMismatch(Object actual, String requiredType)
throws JSONException {
if (actual == null) {
throw new JSONException("Value is null.");
} else {
throw new JSONException("Value " + actual
+ " of type " + actual.getClass().getName()
+ " cannot be converted to " + requiredType);
}
}
}
libandroid-json-org-java-20121204-20090211/src/main/java/org/json/JSONArray.java 0000664 0000000 0000000 00000045673 12071360135 0026251 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.json;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
// Note: this class was written without inspecting the non-free org.json sourcecode.
/**
* A dense indexed sequence of values. Values may be any mix of
* {@link JSONObject JSONObjects}, other {@link JSONArray JSONArrays}, Strings,
* Booleans, Integers, Longs, Doubles, {@code null} or {@link JSONObject#NULL}.
* Values may not be {@link Double#isNaN() NaNs}, {@link Double#isInfinite()
* infinities}, or of any type not listed here.
*
*
{@code JSONArray} has the same type coercion behavior and
* optional/mandatory accessors as {@link JSONObject}. See that class'
* documentation for details.
*
*
Warning: this class represents null in two incompatible
* ways: the standard Java {@code null} reference, and the sentinel value {@link
* JSONObject#NULL}. In particular, {@code get} fails if the requested index
* holds the null reference, but succeeds if it holds {@code JSONObject.NULL}.
*
*
Instances of this class are not thread safe. Although this class is
* nonfinal, it was not designed for inheritance and should not be subclassed.
* In particular, self-use by overridable methods is not specified. See
* Effective Java Item 17, "Design and Document or inheritance or else
* prohibit it" for further information.
*/
public class JSONArray {
private final List values;
/**
* Creates a {@code JSONArray} with no values.
*/
public JSONArray() {
values = new ArrayList();
}
/**
* Creates a new {@code JSONArray} by copying all values from the given
* collection.
*
* @param copyFrom a collection whose values are of supported types.
* Unsupported values are not permitted and will yield an array in an
* inconsistent state.
*/
/* Accept a raw type for API compatibility */
public JSONArray(Collection copyFrom) {
this();
Collection> copyFromTyped = (Collection>) copyFrom;
values.addAll(copyFromTyped);
}
/**
* Creates a new {@code JSONArray} with values from the next array in the
* tokener.
*
* @param readFrom a tokener whose nextValue() method will yield a
* {@code JSONArray}.
* @throws JSONException if the parse fails or doesn't yield a
* {@code JSONArray}.
*/
public JSONArray(JSONTokener readFrom) throws JSONException {
/*
* Getting the parser to populate this could get tricky. Instead, just
* parse to temporary JSONArray and then steal the data from that.
*/
Object object = readFrom.nextValue();
if (object instanceof JSONArray) {
values = ((JSONArray) object).values;
} else {
throw JSON.typeMismatch(object, "JSONArray");
}
}
/**
* Creates a new {@code JSONArray} with values from the JSON string.
*
* @param json a JSON-encoded string containing an array.
* @throws JSONException if the parse fails or doesn't yield a {@code
* JSONArray}.
*/
public JSONArray(String json) throws JSONException {
this(new JSONTokener(json));
}
/**
* Returns the number of values in this array.
*/
public int length() {
return values.size();
}
/**
* Appends {@code value} to the end of this array.
*
* @return this array.
*/
public JSONArray put(boolean value) {
values.add(value);
return this;
}
/**
* Appends {@code value} to the end of this array.
*
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
* {@link Double#isInfinite() infinities}.
* @return this array.
*/
public JSONArray put(double value) throws JSONException {
values.add(JSON.checkDouble(value));
return this;
}
/**
* Appends {@code value} to the end of this array.
*
* @return this array.
*/
public JSONArray put(int value) {
values.add(value);
return this;
}
/**
* Appends {@code value} to the end of this array.
*
* @return this array.
*/
public JSONArray put(long value) {
values.add(value);
return this;
}
/**
* Appends {@code value} to the end of this array.
*
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May
* not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
* infinities}. Unsupported values are not permitted and will cause the
* array to be in an inconsistent state.
* @return this array.
*/
public JSONArray put(Object value) {
values.add(value);
return this;
}
/**
* Sets the value at {@code index} to {@code value}, null padding this array
* to the required length if necessary. If a value already exists at {@code
* index}, it will be replaced.
*
* @return this array.
*/
public JSONArray put(int index, boolean value) throws JSONException {
return put(index, (Boolean) value);
}
/**
* Sets the value at {@code index} to {@code value}, null padding this array
* to the required length if necessary. If a value already exists at {@code
* index}, it will be replaced.
*
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
* {@link Double#isInfinite() infinities}.
* @return this array.
*/
public JSONArray put(int index, double value) throws JSONException {
return put(index, (Double) value);
}
/**
* Sets the value at {@code index} to {@code value}, null padding this array
* to the required length if necessary. If a value already exists at {@code
* index}, it will be replaced.
*
* @return this array.
*/
public JSONArray put(int index, int value) throws JSONException {
return put(index, (Integer) value);
}
/**
* Sets the value at {@code index} to {@code value}, null padding this array
* to the required length if necessary. If a value already exists at {@code
* index}, it will be replaced.
*
* @return this array.
*/
public JSONArray put(int index, long value) throws JSONException {
return put(index, (Long) value);
}
/**
* Sets the value at {@code index} to {@code value}, null padding this array
* to the required length if necessary. If a value already exists at {@code
* index}, it will be replaced.
*
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May
* not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
* infinities}.
* @return this array.
*/
public JSONArray put(int index, Object value) throws JSONException {
if (value instanceof Number) {
// deviate from the original by checking all Numbers, not just floats & doubles
JSON.checkDouble(((Number) value).doubleValue());
}
while (values.size() <= index) {
values.add(null);
}
values.set(index, value);
return this;
}
/**
* Returns true if this array has no value at {@code index}, or if its value
* is the {@code null} reference or {@link JSONObject#NULL}.
*/
public boolean isNull(int index) {
Object value = opt(index);
return value == null || value == JSONObject.NULL;
}
/**
* Returns the value at {@code index}.
*
* @throws JSONException if this array has no value at {@code index}, or if
* that value is the {@code null} reference. This method returns
* normally if the value is {@code JSONObject#NULL}.
*/
public Object get(int index) throws JSONException {
try {
Object value = values.get(index);
if (value == null) {
throw new JSONException("Value at " + index + " is null.");
}
return value;
} catch (IndexOutOfBoundsException e) {
throw new JSONException("Index " + index + " out of range [0.." + values.size() + ")");
}
}
/**
* Returns the value at {@code index}, or null if the array has no value
* at {@code index}.
*/
public Object opt(int index) {
if (index < 0 || index >= values.size()) {
return null;
}
return values.get(index);
}
/**
* Returns the value at {@code index} if it exists and is a boolean or can
* be coerced to a boolean.
*
* @throws JSONException if the value at {@code index} doesn't exist or
* cannot be coerced to a boolean.
*/
public boolean getBoolean(int index) throws JSONException {
Object object = get(index);
Boolean result = JSON.toBoolean(object);
if (result == null) {
throw JSON.typeMismatch(index, object, "boolean");
}
return result;
}
/**
* Returns the value at {@code index} if it exists and is a boolean or can
* be coerced to a boolean. Returns false otherwise.
*/
public boolean optBoolean(int index) {
return optBoolean(index, false);
}
/**
* Returns the value at {@code index} if it exists and is a boolean or can
* be coerced to a boolean. Returns {@code fallback} otherwise.
*/
public boolean optBoolean(int index, boolean fallback) {
Object object = opt(index);
Boolean result = JSON.toBoolean(object);
return result != null ? result : fallback;
}
/**
* Returns the value at {@code index} if it exists and is a double or can
* be coerced to a double.
*
* @throws JSONException if the value at {@code index} doesn't exist or
* cannot be coerced to a double.
*/
public double getDouble(int index) throws JSONException {
Object object = get(index);
Double result = JSON.toDouble(object);
if (result == null) {
throw JSON.typeMismatch(index, object, "double");
}
return result;
}
/**
* Returns the value at {@code index} if it exists and is a double or can
* be coerced to a double. Returns {@code NaN} otherwise.
*/
public double optDouble(int index) {
return optDouble(index, Double.NaN);
}
/**
* Returns the value at {@code index} if it exists and is a double or can
* be coerced to a double. Returns {@code fallback} otherwise.
*/
public double optDouble(int index, double fallback) {
Object object = opt(index);
Double result = JSON.toDouble(object);
return result != null ? result : fallback;
}
/**
* Returns the value at {@code index} if it exists and is an int or
* can be coerced to an int.
*
* @throws JSONException if the value at {@code index} doesn't exist or
* cannot be coerced to a int.
*/
public int getInt(int index) throws JSONException {
Object object = get(index);
Integer result = JSON.toInteger(object);
if (result == null) {
throw JSON.typeMismatch(index, object, "int");
}
return result;
}
/**
* Returns the value at {@code index} if it exists and is an int or
* can be coerced to an int. Returns 0 otherwise.
*/
public int optInt(int index) {
return optInt(index, 0);
}
/**
* Returns the value at {@code index} if it exists and is an int or
* can be coerced to an int. Returns {@code fallback} otherwise.
*/
public int optInt(int index, int fallback) {
Object object = opt(index);
Integer result = JSON.toInteger(object);
return result != null ? result : fallback;
}
/**
* Returns the value at {@code index} if it exists and is a long or
* can be coerced to a long.
*
* @throws JSONException if the value at {@code index} doesn't exist or
* cannot be coerced to a long.
*/
public long getLong(int index) throws JSONException {
Object object = get(index);
Long result = JSON.toLong(object);
if (result == null) {
throw JSON.typeMismatch(index, object, "long");
}
return result;
}
/**
* Returns the value at {@code index} if it exists and is a long or
* can be coerced to a long. Returns 0 otherwise.
*/
public long optLong(int index) {
return optLong(index, 0L);
}
/**
* Returns the value at {@code index} if it exists and is a long or
* can be coerced to a long. Returns {@code fallback} otherwise.
*/
public long optLong(int index, long fallback) {
Object object = opt(index);
Long result = JSON.toLong(object);
return result != null ? result : fallback;
}
/**
* Returns the value at {@code index} if it exists, coercing it if
* necessary.
*
* @throws JSONException if no such value exists.
*/
public String getString(int index) throws JSONException {
Object object = get(index);
String result = JSON.toString(object);
if (result == null) {
throw JSON.typeMismatch(index, object, "String");
}
return result;
}
/**
* Returns the value at {@code index} if it exists, coercing it if
* necessary. Returns the empty string if no such value exists.
*/
public String optString(int index) {
return optString(index, "");
}
/**
* Returns the value at {@code index} if it exists, coercing it if
* necessary. Returns {@code fallback} if no such value exists.
*/
public String optString(int index, String fallback) {
Object object = opt(index);
String result = JSON.toString(object);
return result != null ? result : fallback;
}
/**
* Returns the value at {@code index} if it exists and is a {@code
* JSONArray}.
*
* @throws JSONException if the value doesn't exist or is not a {@code
* JSONArray}.
*/
public JSONArray getJSONArray(int index) throws JSONException {
Object object = get(index);
if (object instanceof JSONArray) {
return (JSONArray) object;
} else {
throw JSON.typeMismatch(index, object, "JSONArray");
}
}
/**
* Returns the value at {@code index} if it exists and is a {@code
* JSONArray}. Returns null otherwise.
*/
public JSONArray optJSONArray(int index) {
Object object = opt(index);
return object instanceof JSONArray ? (JSONArray) object : null;
}
/**
* Returns the value at {@code index} if it exists and is a {@code
* JSONObject}.
*
* @throws JSONException if the value doesn't exist or is not a {@code
* JSONObject}.
*/
public JSONObject getJSONObject(int index) throws JSONException {
Object object = get(index);
if (object instanceof JSONObject) {
return (JSONObject) object;
} else {
throw JSON.typeMismatch(index, object, "JSONObject");
}
}
/**
* Returns the value at {@code index} if it exists and is a {@code
* JSONObject}. Returns null otherwise.
*/
public JSONObject optJSONObject(int index) {
Object object = opt(index);
return object instanceof JSONObject ? (JSONObject) object : null;
}
/**
* Returns a new object whose values are the values in this array, and whose
* names are the values in {@code names}. Names and values are paired up by
* index from 0 through to the shorter array's length. Names that are not
* strings will be coerced to strings. This method returns null if either
* array is empty.
*/
public JSONObject toJSONObject(JSONArray names) throws JSONException {
JSONObject result = new JSONObject();
int length = Math.min(names.length(), values.size());
if (length == 0) {
return null;
}
for (int i = 0; i < length; i++) {
String name = JSON.toString(names.opt(i));
result.put(name, opt(i));
}
return result;
}
/**
* Returns a new string by alternating this array's values with {@code
* separator}. This array's string values are quoted and have their special
* characters escaped. For example, the array containing the strings '12"
* pizza', 'taco' and 'soda' joined on '+' returns this:
* "12\" pizza"+"taco"+"soda"
*/
public String join(String separator) throws JSONException {
JSONStringer stringer = new JSONStringer();
stringer.open(JSONStringer.Scope.NULL, "");
for (int i = 0, size = values.size(); i < size; i++) {
if (i > 0) {
stringer.out.append(separator);
}
stringer.value(values.get(i));
}
stringer.close(JSONStringer.Scope.NULL, JSONStringer.Scope.NULL, "");
return stringer.out.toString();
}
/**
* Encodes this array as a compact JSON string, such as:
* [94043,90210]
*/
@Override public String toString() {
try {
JSONStringer stringer = new JSONStringer();
writeTo(stringer);
return stringer.toString();
} catch (JSONException e) {
return null;
}
}
/**
* Encodes this array as a human readable JSON string for debugging, such
* as:
*
* [
* 94043,
* 90210
* ]
*
* @param indentSpaces the number of spaces to indent for each level of
* nesting.
*/
public String toString(int indentSpaces) throws JSONException {
JSONStringer stringer = new JSONStringer(indentSpaces);
writeTo(stringer);
return stringer.toString();
}
void writeTo(JSONStringer stringer) throws JSONException {
stringer.array();
for (Object value : values) {
stringer.value(value);
}
stringer.endArray();
}
@Override public boolean equals(Object o) {
return o instanceof JSONArray && ((JSONArray) o).values.equals(values);
}
@Override public int hashCode() {
// diverge from the original, which doesn't implement hashCode
return values.hashCode();
}
}
libandroid-json-org-java-20121204-20090211/src/main/java/org/json/JSONException.java 0000664 0000000 0000000 00000003164 12071360135 0027116 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.json;
// Note: this class was written without inspecting the non-free org.json sourcecode.
/**
* Thrown to indicate a problem with the JSON API. Such problems include:
*
* Attempts to parse or construct malformed documents
* Use of null as a name
* Use of numeric types not available to JSON, such as {@link
* Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}.
* Lookups using an out of range index or nonexistent name
* Type mismatches on lookups
*
*
* Although this is a checked exception, it is rarely recoverable. Most
* callers should simply wrap this exception in an unchecked exception and
* rethrow:
*
public JSONArray toJSONObject() {
* try {
* JSONObject result = new JSONObject();
* ...
* } catch (JSONException e) {
* throw new RuntimeException(e);
* }
* }
*/
public class JSONException extends Exception {
public JSONException(String s) {
super(s);
}
}
libandroid-json-org-java-20121204-20090211/src/main/java/org/json/JSONObject.java 0000664 0000000 0000000 00000060644 12071360135 0026374 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.json;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
// Note: this class was written without inspecting the non-free org.json sourcecode.
/**
* A modifiable set of name/value mappings. Names are unique, non-null strings.
* Values may be any mix of {@link JSONObject JSONObjects}, {@link JSONArray
* JSONArrays}, Strings, Booleans, Integers, Longs, Doubles or {@link #NULL}.
* Values may not be {@code null}, {@link Double#isNaN() NaNs}, {@link
* Double#isInfinite() infinities}, or of any type not listed here.
*
* This class can coerce values to another type when requested.
*
* When the requested type is a boolean, strings will be coerced using a
* case-insensitive comparison to "true" and "false".
* When the requested type is a double, other {@link Number} types will
* be coerced using {@link Number#doubleValue() doubleValue}. Strings
* that can be coerced using {@link Double#valueOf(String)} will be.
* When the requested type is an int, other {@link Number} types will
* be coerced using {@link Number#intValue() intValue}. Strings
* that can be coerced using {@link Double#valueOf(String)} will be,
* and then cast to int.
* When the requested type is a long, other {@link Number} types will
* be coerced using {@link Number#longValue() longValue}. Strings
* that can be coerced using {@link Double#valueOf(String)} will be,
* and then cast to long. This two-step conversion is lossy for very
* large values. For example, the string "9223372036854775806" yields the
* long 9223372036854775807.
* When the requested type is a String, other non-null values will be
* coerced using {@link String#valueOf(Object)}. Although null cannot be
* coerced, the sentinel value {@link JSONObject#NULL} is coerced to the
* string "null".
*
*
* This class can look up both mandatory and optional values:
*
* Use getType ()
to retrieve a mandatory value. This
* fails with a {@code JSONException} if the requested name has no value
* or if the value cannot be coerced to the requested type.
* Use optType ()
to retrieve an optional value. This
* returns a system- or user-supplied default if the requested name has no
* value or if the value cannot be coerced to the requested type.
*
*
* Warning: this class represents null in two incompatible
* ways: the standard Java {@code null} reference, and the sentinel value {@link
* JSONObject#NULL}. In particular, calling {@code put(name, null)} removes the
* named entry from the object but {@code put(name, JSONObject.NULL)} stores an
* entry whose value is {@code JSONObject.NULL}.
*
*
Instances of this class are not thread safe. Although this class is
* nonfinal, it was not designed for inheritance and should not be subclassed.
* In particular, self-use by overrideable methods is not specified. See
* Effective Java Item 17, "Design and Document or inheritance or else
* prohibit it" for further information.
*/
public class JSONObject {
private static final Double NEGATIVE_ZERO = -0d;
/**
* A sentinel value used to explicitly define a name with no value. Unlike
* {@code null}, names with this value:
*
* show up in the {@link #names} array
* show up in the {@link #keys} iterator
* return {@code true} for {@link #has(String)}
* do not throw on {@link #get(String)}
* are included in the encoded JSON string.
*
*
* This value violates the general contract of {@link Object#equals} by
* returning true when compared to {@code null}. Its {@link #toString}
* method returns "null".
*/
public static final Object NULL = new Object() {
@Override public boolean equals(Object o) {
return o == this || o == null; // API specifies this broken equals implementation
}
@Override public String toString() {
return "null";
}
};
private final Map nameValuePairs;
/**
* Creates a {@code JSONObject} with no name/value mappings.
*/
public JSONObject() {
nameValuePairs = new HashMap();
}
/**
* Creates a new {@code JSONObject} by copying all name/value mappings from
* the given map.
*
* @param copyFrom a map whose keys are of type {@link String} and whose
* values are of supported types.
* @throws NullPointerException if any of the map's keys are null.
*/
/* (accept a raw type for API compatibility) */
public JSONObject(Map copyFrom) {
this();
Map, ?> contentsTyped = (Map, ?>) copyFrom;
for (Map.Entry, ?> entry : contentsTyped.entrySet()) {
/*
* Deviate from the original by checking that keys are non-null and
* of the proper type. (We still defer validating the values).
*/
String key = (String) entry.getKey();
if (key == null) {
throw new NullPointerException("key == null");
}
nameValuePairs.put(key, entry.getValue());
}
}
/**
* Creates a new {@code JSONObject} with name/value mappings from the next
* object in the tokener.
*
* @param readFrom a tokener whose nextValue() method will yield a
* {@code JSONObject}.
* @throws JSONException if the parse fails or doesn't yield a
* {@code JSONObject}.
*/
public JSONObject(JSONTokener readFrom) throws JSONException {
/*
* Getting the parser to populate this could get tricky. Instead, just
* parse to temporary JSONObject and then steal the data from that.
*/
Object object = readFrom.nextValue();
if (object instanceof JSONObject) {
this.nameValuePairs = ((JSONObject) object).nameValuePairs;
} else {
throw JSON.typeMismatch(object, "JSONObject");
}
}
/**
* Creates a new {@code JSONObject} with name/value mappings from the JSON
* string.
*
* @param json a JSON-encoded string containing an object.
* @throws JSONException if the parse fails or doesn't yield a {@code
* JSONObject}.
*/
public JSONObject(String json) throws JSONException {
this(new JSONTokener(json));
}
/**
* Creates a new {@code JSONObject} by copying mappings for the listed names
* from the given object. Names that aren't present in {@code copyFrom} will
* be skipped.
*/
public JSONObject(JSONObject copyFrom, String[] names) throws JSONException {
this();
for (String name : names) {
Object value = copyFrom.opt(name);
if (value != null) {
nameValuePairs.put(name, value);
}
}
}
/**
* Returns the number of name/value mappings in this object.
*/
public int length() {
return nameValuePairs.size();
}
/**
* Maps {@code name} to {@code value}, clobbering any existing name/value
* mapping with the same name.
*
* @return this object.
*/
public JSONObject put(String name, boolean value) throws JSONException {
nameValuePairs.put(checkName(name), value);
return this;
}
/**
* Maps {@code name} to {@code value}, clobbering any existing name/value
* mapping with the same name.
*
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
* {@link Double#isInfinite() infinities}.
* @return this object.
*/
public JSONObject put(String name, double value) throws JSONException {
nameValuePairs.put(checkName(name), JSON.checkDouble(value));
return this;
}
/**
* Maps {@code name} to {@code value}, clobbering any existing name/value
* mapping with the same name.
*
* @return this object.
*/
public JSONObject put(String name, int value) throws JSONException {
nameValuePairs.put(checkName(name), value);
return this;
}
/**
* Maps {@code name} to {@code value}, clobbering any existing name/value
* mapping with the same name.
*
* @return this object.
*/
public JSONObject put(String name, long value) throws JSONException {
nameValuePairs.put(checkName(name), value);
return this;
}
/**
* Maps {@code name} to {@code value}, clobbering any existing name/value
* mapping with the same name. If the value is {@code null}, any existing
* mapping for {@code name} is removed.
*
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double, {@link #NULL}, or {@code null}. May not be
* {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
* infinities}.
* @return this object.
*/
public JSONObject put(String name, Object value) throws JSONException {
if (value == null) {
nameValuePairs.remove(name);
return this;
}
if (value instanceof Number) {
// deviate from the original by checking all Numbers, not just floats & doubles
JSON.checkDouble(((Number) value).doubleValue());
}
nameValuePairs.put(checkName(name), value);
return this;
}
/**
* Equivalent to {@code put(name, value)} when both parameters are non-null;
* does nothing otherwise.
*/
public JSONObject putOpt(String name, Object value) throws JSONException {
if (name == null || value == null) {
return this;
}
return put(name, value);
}
/**
* Appends {@code value} to the array already mapped to {@code name}. If
* this object has no mapping for {@code name}, this inserts a new mapping.
* If the mapping exists but its value is not an array, the existing
* and new values are inserted in order into a new array which is itself
* mapped to {@code name}. In aggregate, this allows values to be added to a
* mapping one at a time.
*
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double, {@link #NULL} or null. May not be {@link
* Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}.
*/
public JSONObject accumulate(String name, Object value) throws JSONException {
Object current = nameValuePairs.get(checkName(name));
if (current == null) {
return put(name, value);
}
// check in accumulate, since array.put(Object) doesn't do any checking
if (value instanceof Number) {
JSON.checkDouble(((Number) value).doubleValue());
}
if (current instanceof JSONArray) {
JSONArray array = (JSONArray) current;
array.put(value);
} else {
JSONArray array = new JSONArray();
array.put(current);
array.put(value);
nameValuePairs.put(name, array);
}
return this;
}
String checkName(String name) throws JSONException {
if (name == null) {
throw new JSONException("Names must be non-null");
}
return name;
}
/**
* Removes the named mapping if it exists; does nothing otherwise.
*
* @return the value previously mapped by {@code name}, or null if there was
* no such mapping.
*/
public Object remove(String name) {
return nameValuePairs.remove(name);
}
/**
* Returns true if this object has no mapping for {@code name} or if it has
* a mapping whose value is {@link #NULL}.
*/
public boolean isNull(String name) {
Object value = nameValuePairs.get(name);
return value == null || value == NULL;
}
/**
* Returns true if this object has a mapping for {@code name}. The mapping
* may be {@link #NULL}.
*/
public boolean has(String name) {
return nameValuePairs.containsKey(name);
}
/**
* Returns the value mapped by {@code name}.
*
* @throws JSONException if no such mapping exists.
*/
public Object get(String name) throws JSONException {
Object result = nameValuePairs.get(name);
if (result == null) {
throw new JSONException("No value for " + name);
}
return result;
}
/**
* Returns the value mapped by {@code name}, or null if no such mapping
* exists.
*/
public Object opt(String name) {
return nameValuePairs.get(name);
}
/**
* Returns the value mapped by {@code name} if it exists and is a boolean or
* can be coerced to a boolean.
*
* @throws JSONException if the mapping doesn't exist or cannot be coerced
* to a boolean.
*/
public boolean getBoolean(String name) throws JSONException {
Object object = get(name);
Boolean result = JSON.toBoolean(object);
if (result == null) {
throw JSON.typeMismatch(name, object, "boolean");
}
return result;
}
/**
* Returns the value mapped by {@code name} if it exists and is a boolean or
* can be coerced to a boolean. Returns false otherwise.
*/
public boolean optBoolean(String name) {
return optBoolean(name, false);
}
/**
* Returns the value mapped by {@code name} if it exists and is a boolean or
* can be coerced to a boolean. Returns {@code fallback} otherwise.
*/
public boolean optBoolean(String name, boolean fallback) {
Object object = opt(name);
Boolean result = JSON.toBoolean(object);
return result != null ? result : fallback;
}
/**
* Returns the value mapped by {@code name} if it exists and is a double or
* can be coerced to a double.
*
* @throws JSONException if the mapping doesn't exist or cannot be coerced
* to a double.
*/
public double getDouble(String name) throws JSONException {
Object object = get(name);
Double result = JSON.toDouble(object);
if (result == null) {
throw JSON.typeMismatch(name, object, "double");
}
return result;
}
/**
* Returns the value mapped by {@code name} if it exists and is a double or
* can be coerced to a double. Returns {@code NaN} otherwise.
*/
public double optDouble(String name) {
return optDouble(name, Double.NaN);
}
/**
* Returns the value mapped by {@code name} if it exists and is a double or
* can be coerced to a double. Returns {@code fallback} otherwise.
*/
public double optDouble(String name, double fallback) {
Object object = opt(name);
Double result = JSON.toDouble(object);
return result != null ? result : fallback;
}
/**
* Returns the value mapped by {@code name} if it exists and is an int or
* can be coerced to an int.
*
* @throws JSONException if the mapping doesn't exist or cannot be coerced
* to an int.
*/
public int getInt(String name) throws JSONException {
Object object = get(name);
Integer result = JSON.toInteger(object);
if (result == null) {
throw JSON.typeMismatch(name, object, "int");
}
return result;
}
/**
* Returns the value mapped by {@code name} if it exists and is an int or
* can be coerced to an int. Returns 0 otherwise.
*/
public int optInt(String name) {
return optInt(name, 0);
}
/**
* Returns the value mapped by {@code name} if it exists and is an int or
* can be coerced to an int. Returns {@code fallback} otherwise.
*/
public int optInt(String name, int fallback) {
Object object = opt(name);
Integer result = JSON.toInteger(object);
return result != null ? result : fallback;
}
/**
* Returns the value mapped by {@code name} if it exists and is a long or
* can be coerced to a long.
*
* @throws JSONException if the mapping doesn't exist or cannot be coerced
* to a long.
*/
public long getLong(String name) throws JSONException {
Object object = get(name);
Long result = JSON.toLong(object);
if (result == null) {
throw JSON.typeMismatch(name, object, "long");
}
return result;
}
/**
* Returns the value mapped by {@code name} if it exists and is a long or
* can be coerced to a long. Returns 0 otherwise.
*/
public long optLong(String name) {
return optLong(name, 0L);
}
/**
* Returns the value mapped by {@code name} if it exists and is a long or
* can be coerced to a long. Returns {@code fallback} otherwise.
*/
public long optLong(String name, long fallback) {
Object object = opt(name);
Long result = JSON.toLong(object);
return result != null ? result : fallback;
}
/**
* Returns the value mapped by {@code name} if it exists, coercing it if
* necessary.
*
* @throws JSONException if no such mapping exists.
*/
public String getString(String name) throws JSONException {
Object object = get(name);
String result = JSON.toString(object);
if (result == null) {
throw JSON.typeMismatch(name, object, "String");
}
return result;
}
/**
* Returns the value mapped by {@code name} if it exists, coercing it if
* necessary. Returns the empty string if no such mapping exists.
*/
public String optString(String name) {
return optString(name, "");
}
/**
* Returns the value mapped by {@code name} if it exists, coercing it if
* necessary. Returns {@code fallback} if no such mapping exists.
*/
public String optString(String name, String fallback) {
Object object = opt(name);
String result = JSON.toString(object);
return result != null ? result : fallback;
}
/**
* Returns the value mapped by {@code name} if it exists and is a {@code
* JSONArray}.
*
* @throws JSONException if the mapping doesn't exist or is not a {@code
* JSONArray}.
*/
public JSONArray getJSONArray(String name) throws JSONException {
Object object = get(name);
if (object instanceof JSONArray) {
return (JSONArray) object;
} else {
throw JSON.typeMismatch(name, object, "JSONArray");
}
}
/**
* Returns the value mapped by {@code name} if it exists and is a {@code
* JSONArray}. Returns null otherwise.
*/
public JSONArray optJSONArray(String name) {
Object object = opt(name);
return object instanceof JSONArray ? (JSONArray) object : null;
}
/**
* Returns the value mapped by {@code name} if it exists and is a {@code
* JSONObject}.
*
* @throws JSONException if the mapping doesn't exist or is not a {@code
* JSONObject}.
*/
public JSONObject getJSONObject(String name) throws JSONException {
Object object = get(name);
if (object instanceof JSONObject) {
return (JSONObject) object;
} else {
throw JSON.typeMismatch(name, object, "JSONObject");
}
}
/**
* Returns the value mapped by {@code name} if it exists and is a {@code
* JSONObject}. Returns null otherwise.
*/
public JSONObject optJSONObject(String name) {
Object object = opt(name);
return object instanceof JSONObject ? (JSONObject) object : null;
}
/**
* Returns an array with the values corresponding to {@code names}. The
* array contains null for names that aren't mapped. This method returns
* null if {@code names} is either null or empty.
*/
public JSONArray toJSONArray(JSONArray names) throws JSONException {
JSONArray result = new JSONArray();
if (names == null) {
return null;
}
int length = names.length();
if (length == 0) {
return null;
}
for (int i = 0; i < length; i++) {
String name = JSON.toString(names.opt(i));
result.put(opt(name));
}
return result;
}
/**
* Returns an iterator of the {@code String} names in this object. The
* returned iterator supports {@link Iterator#remove() remove}, which will
* remove the corresponding mapping from this object. If this object is
* modified after the iterator is returned, the iterator's behavior is
* undefined. The order of the keys is undefined.
*/
/* Return a raw type for API compatibility */
public Iterator keys() {
return nameValuePairs.keySet().iterator();
}
/**
* Returns an array containing the string names in this object. This method
* returns null if this object contains no mappings.
*/
public JSONArray names() {
return nameValuePairs.isEmpty()
? null
: new JSONArray(new ArrayList(nameValuePairs.keySet()));
}
/**
* Encodes this object as a compact JSON string, such as:
* {"query":"Pizza","locations":[94043,90210]}
*/
@Override public String toString() {
try {
JSONStringer stringer = new JSONStringer();
writeTo(stringer);
return stringer.toString();
} catch (JSONException e) {
return null;
}
}
/**
* Encodes this object as a human readable JSON string for debugging, such
* as:
*
* {
* "query": "Pizza",
* "locations": [
* 94043,
* 90210
* ]
* }
*
* @param indentSpaces the number of spaces to indent for each level of
* nesting.
*/
public String toString(int indentSpaces) throws JSONException {
JSONStringer stringer = new JSONStringer(indentSpaces);
writeTo(stringer);
return stringer.toString();
}
void writeTo(JSONStringer stringer) throws JSONException {
stringer.object();
for (Map.Entry entry : nameValuePairs.entrySet()) {
stringer.key(entry.getKey()).value(entry.getValue());
}
stringer.endObject();
}
/**
* Encodes the number as a JSON string.
*
* @param number a finite value. May not be {@link Double#isNaN() NaNs} or
* {@link Double#isInfinite() infinities}.
*/
public static String numberToString(Number number) throws JSONException {
if (number == null) {
throw new JSONException("Number must be non-null");
}
double doubleValue = number.doubleValue();
JSON.checkDouble(doubleValue);
// the original returns "-0" instead of "-0.0" for negative zero
if (number.equals(NEGATIVE_ZERO)) {
return "-0";
}
long longValue = number.longValue();
if (doubleValue == (double) longValue) {
return Long.toString(longValue);
}
return number.toString();
}
/**
* Encodes {@code data} as a JSON string. This applies quotes and any
* necessary character escaping.
*
* @param data the string to encode. Null will be interpreted as an empty
* string.
*/
public static String quote(String data) {
if (data == null) {
return "\"\"";
}
try {
JSONStringer stringer = new JSONStringer();
stringer.open(JSONStringer.Scope.NULL, "");
stringer.value(data);
stringer.close(JSONStringer.Scope.NULL, JSONStringer.Scope.NULL, "");
return stringer.toString();
} catch (JSONException e) {
throw new AssertionError();
}
}
}
libandroid-json-org-java-20121204-20090211/src/main/java/org/json/JSONStringer.java 0000664 0000000 0000000 00000031602 12071360135 0026753 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.json;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
// Note: this class was written without inspecting the non-free org.json sourcecode.
/**
* Implements {@link JSONObject#toString} and {@link JSONArray#toString}. Most
* application developers should use those methods directly and disregard this
* API. For example:
* JSONObject object = ...
* String json = object.toString();
*
* Stringers only encode well-formed JSON strings. In particular:
*
* The stringer must have exactly one top-level array or object.
* Lexical scopes must be balanced: every call to {@link #array} must
* have a matching call to {@link #endArray} and every call to {@link
* #object} must have a matching call to {@link #endObject}.
* Arrays may not contain keys (property names).
* Objects must alternate keys (property names) and values.
* Values are inserted with either literal {@link #value(Object) value}
* calls, or by nesting arrays or objects.
*
* Calls that would result in a malformed JSON string will fail with a
* {@link JSONException}.
*
* This class provides no facility for pretty-printing (ie. indenting)
* output. To encode indented output, use {@link JSONObject#toString(int)} or
* {@link JSONArray#toString(int)}.
*
*
Some implementations of the API support at most 20 levels of nesting.
* Attempts to create more than 20 levels of nesting may fail with a {@link
* JSONException}.
*
*
Each stringer may be used to encode a single top level value. Instances of
* this class are not thread safe. Although this class is nonfinal, it was not
* designed for inheritance and should not be subclassed. In particular,
* self-use by overrideable methods is not specified. See Effective Java
* Item 17, "Design and Document or inheritance or else prohibit it" for further
* information.
*/
public class JSONStringer {
/** The output data, containing at most one top-level array or object. */
final StringBuilder out = new StringBuilder();
/**
* Lexical scoping elements within this stringer, necessary to insert the
* appropriate separator characters (ie. commas and colons) and to detect
* nesting errors.
*/
enum Scope {
/**
* An array with no elements requires no separators or newlines before
* it is closed.
*/
EMPTY_ARRAY,
/**
* A array with at least one value requires a comma and newline before
* the next element.
*/
NONEMPTY_ARRAY,
/**
* An object with no keys or values requires no separators or newlines
* before it is closed.
*/
EMPTY_OBJECT,
/**
* An object whose most recent element is a key. The next element must
* be a value.
*/
DANGLING_KEY,
/**
* An object with at least one name/value pair requires a comma and
* newline before the next element.
*/
NONEMPTY_OBJECT,
/**
* A special bracketless array needed by JSONStringer.join() and
* JSONObject.quote() only. Not used for JSON encoding.
*/
NULL,
}
/**
* Unlike the original implementation, this stack isn't limited to 20
* levels of nesting.
*/
private final List stack = new ArrayList();
/**
* A string containing a full set of spaces for a single level of
* indentation, or null for no pretty printing.
*/
private final String indent;
public JSONStringer() {
indent = null;
}
JSONStringer(int indentSpaces) {
char[] indentChars = new char[indentSpaces];
Arrays.fill(indentChars, ' ');
indent = new String(indentChars);
}
/**
* Begins encoding a new array. Each call to this method must be paired with
* a call to {@link #endArray}.
*
* @return this stringer.
*/
public JSONStringer array() throws JSONException {
return open(Scope.EMPTY_ARRAY, "[");
}
/**
* Ends encoding the current array.
*
* @return this stringer.
*/
public JSONStringer endArray() throws JSONException {
return close(Scope.EMPTY_ARRAY, Scope.NONEMPTY_ARRAY, "]");
}
/**
* Begins encoding a new object. Each call to this method must be paired
* with a call to {@link #endObject}.
*
* @return this stringer.
*/
public JSONStringer object() throws JSONException {
return open(Scope.EMPTY_OBJECT, "{");
}
/**
* Ends encoding the current object.
*
* @return this stringer.
*/
public JSONStringer endObject() throws JSONException {
return close(Scope.EMPTY_OBJECT, Scope.NONEMPTY_OBJECT, "}");
}
/**
* Enters a new scope by appending any necessary whitespace and the given
* bracket.
*/
JSONStringer open(Scope empty, String openBracket) throws JSONException {
if (stack.isEmpty() && out.length() > 0) {
throw new JSONException("Nesting problem: multiple top-level roots");
}
beforeValue();
stack.add(empty);
out.append(openBracket);
return this;
}
/**
* Closes the current scope by appending any necessary whitespace and the
* given bracket.
*/
JSONStringer close(Scope empty, Scope nonempty, String closeBracket) throws JSONException {
Scope context = peek();
if (context != nonempty && context != empty) {
throw new JSONException("Nesting problem");
}
stack.remove(stack.size() - 1);
if (context == nonempty) {
newline();
}
out.append(closeBracket);
return this;
}
/**
* Returns the value on the top of the stack.
*/
private Scope peek() throws JSONException {
if (stack.isEmpty()) {
throw new JSONException("Nesting problem");
}
return stack.get(stack.size() - 1);
}
/**
* Replace the value on the top of the stack with the given value.
*/
private void replaceTop(Scope topOfStack) {
stack.set(stack.size() - 1, topOfStack);
}
/**
* Encodes {@code value}.
*
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double or null. May not be {@link Double#isNaN() NaNs}
* or {@link Double#isInfinite() infinities}.
* @return this stringer.
*/
public JSONStringer value(Object value) throws JSONException {
if (stack.isEmpty()) {
throw new JSONException("Nesting problem");
}
if (value instanceof JSONArray) {
((JSONArray) value).writeTo(this);
return this;
} else if (value instanceof JSONObject) {
((JSONObject) value).writeTo(this);
return this;
}
beforeValue();
if (value == null
|| value instanceof Boolean
|| value == JSONObject.NULL) {
out.append(value);
} else if (value instanceof Number) {
out.append(JSONObject.numberToString((Number) value));
} else {
string(value.toString());
}
return this;
}
/**
* Encodes {@code value} to this stringer.
*
* @return this stringer.
*/
public JSONStringer value(boolean value) throws JSONException {
if (stack.isEmpty()) {
throw new JSONException("Nesting problem");
}
beforeValue();
out.append(value);
return this;
}
/**
* Encodes {@code value} to this stringer.
*
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
* {@link Double#isInfinite() infinities}.
* @return this stringer.
*/
public JSONStringer value(double value) throws JSONException {
if (stack.isEmpty()) {
throw new JSONException("Nesting problem");
}
beforeValue();
out.append(JSONObject.numberToString(value));
return this;
}
/**
* Encodes {@code value} to this stringer.
*
* @return this stringer.
*/
public JSONStringer value(long value) throws JSONException {
if (stack.isEmpty()) {
throw new JSONException("Nesting problem");
}
beforeValue();
out.append(value);
return this;
}
private void string(String value) {
out.append("\"");
for (int i = 0, length = value.length(); i < length; i++) {
char c = value.charAt(i);
/*
* From RFC 4627, "All Unicode characters may be placed within the
* quotation marks except for the characters that must be escaped:
* quotation mark, reverse solidus, and the control characters
* (U+0000 through U+001F)."
*/
switch (c) {
case '"':
case '\\':
case '/':
out.append('\\').append(c);
break;
case '\t':
out.append("\\t");
break;
case '\b':
out.append("\\b");
break;
case '\n':
out.append("\\n");
break;
case '\r':
out.append("\\r");
break;
case '\f':
out.append("\\f");
break;
default:
if (c <= 0x1F) {
out.append(String.format("\\u%04x", (int) c));
} else {
out.append(c);
}
break;
}
}
out.append("\"");
}
private void newline() {
if (indent == null) {
return;
}
out.append("\n");
for (int i = 0; i < stack.size(); i++) {
out.append(indent);
}
}
/**
* Encodes the key (property name) to this stringer.
*
* @param name the name of the forthcoming value. May not be null.
* @return this stringer.
*/
public JSONStringer key(String name) throws JSONException {
if (name == null) {
throw new JSONException("Names must be non-null");
}
beforeKey();
string(name);
return this;
}
/**
* Inserts any necessary separators and whitespace before a name. Also
* adjusts the stack to expect the key's value.
*/
private void beforeKey() throws JSONException {
Scope context = peek();
if (context == Scope.NONEMPTY_OBJECT) { // first in object
out.append(',');
} else if (context != Scope.EMPTY_OBJECT) { // not in an object!
throw new JSONException("Nesting problem");
}
newline();
replaceTop(Scope.DANGLING_KEY);
}
/**
* Inserts any necessary separators and whitespace before a literal value,
* inline array, or inline object. Also adjusts the stack to expect either a
* closing bracket or another element.
*/
private void beforeValue() throws JSONException {
if (stack.isEmpty()) {
return;
}
Scope context = peek();
if (context == Scope.EMPTY_ARRAY) { // first in array
replaceTop(Scope.NONEMPTY_ARRAY);
newline();
} else if (context == Scope.NONEMPTY_ARRAY) { // another in array
out.append(',');
newline();
} else if (context == Scope.DANGLING_KEY) { // value for key
out.append(indent == null ? ":" : ": ");
replaceTop(Scope.NONEMPTY_OBJECT);
} else if (context != Scope.NULL) {
throw new JSONException("Nesting problem");
}
}
/**
* Returns the encoded JSON string.
*
* If invoked with unterminated arrays or unclosed objects, this method's
* return value is undefined.
*
*
Warning: although it contradicts the general contract
* of {@link Object#toString}, this method returns null if the stringer
* contains no data.
*/
@Override public String toString() {
return out.length() == 0 ? null : out.toString();
}
}
libandroid-json-org-java-20121204-20090211/src/main/java/org/json/JSONTokener.java 0000664 0000000 0000000 00000050244 12071360135 0026570 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.json;
// Note: this class was written without inspecting the non-free org.json sourcecode.
/**
* Parses a JSON (RFC 4627 )
* encoded string into the corresponding object. Most clients of
* this class will use only need the {@link #JSONTokener(String) constructor}
* and {@link #nextValue} method. Example usage:
* String json = "{"
* + " \"query\": \"Pizza\", "
* + " \"locations\": [ 94043, 90210 ] "
* + "}";
*
* JSONObject object = (JSONObject) new JSONTokener(json).nextValue();
* String query = object.getString("query");
* JSONArray locations = object.getJSONArray("locations");
*
* For best interoperability and performance use JSON that complies with
* RFC 4627, such as that generated by {@link JSONStringer}. For legacy reasons
* this parser is lenient, so a successful parse does not indicate that the
* input string was valid JSON. All of the following syntax errors will be
* ignored:
*
* End of line comments starting with {@code //} or {@code #} and ending
* with a newline character.
* C-style comments starting with {@code /*} and ending with
* {@code *}{@code /}. Such comments may not be nested.
* Strings that are unquoted or {@code 'single quoted'}.
* Hexadecimal integers prefixed with {@code 0x} or {@code 0X}.
* Octal integers prefixed with {@code 0}.
* Array elements separated by {@code ;}.
* Unnecessary array separators. These are interpreted as if null was the
* omitted value.
* Key-value pairs separated by {@code =} or {@code =>}.
* Key-value pairs separated by {@code ;}.
*
*
* Each tokener may be used to parse a single JSON string. Instances of this
* class are not thread safe. Although this class is nonfinal, it was not
* designed for inheritance and should not be subclassed. In particular,
* self-use by overrideable methods is not specified. See Effective Java
* Item 17, "Design and Document or inheritance or else prohibit it" for further
* information.
*/
public class JSONTokener {
/** The input JSON. */
private final String in;
/**
* The index of the next character to be returned by {@link #next}. When
* the input is exhausted, this equals the input's length.
*/
private int pos;
/**
* @param in JSON encoded string. Null is not permitted and will yield a
* tokener that throws {@code NullPointerExceptions} when methods are
* called.
*/
public JSONTokener(String in) {
// consume an optional byte order mark (BOM) if it exists
if (in != null && in.startsWith("\ufeff")) {
in = in.substring(1);
}
this.in = in;
}
/**
* Returns the next value from the input.
*
* @return a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double or {@link JSONObject#NULL}.
* @throws JSONException if the input is malformed.
*/
public Object nextValue() throws JSONException {
int c = nextCleanInternal();
switch (c) {
case -1:
throw syntaxError("End of input");
case '{':
return readObject();
case '[':
return readArray();
case '\'':
case '"':
return nextString((char) c);
default:
pos--;
return readLiteral();
}
}
private int nextCleanInternal() throws JSONException {
while (pos < in.length()) {
int c = in.charAt(pos++);
switch (c) {
case '\t':
case ' ':
case '\n':
case '\r':
continue;
case '/':
if (pos == in.length()) {
return c;
}
char peek = in.charAt(pos);
switch (peek) {
case '*':
// skip a /* c-style comment */
pos++;
int commentEnd = in.indexOf("*/", pos);
if (commentEnd == -1) {
throw syntaxError("Unterminated comment");
}
pos = commentEnd + 2;
continue;
case '/':
// skip a // end-of-line comment
pos++;
skipToEndOfLine();
continue;
default:
return c;
}
case '#':
/*
* Skip a # hash end-of-line comment. The JSON RFC doesn't
* specify this behavior, but it's required to parse
* existing documents. See http://b/2571423.
*/
skipToEndOfLine();
continue;
default:
return c;
}
}
return -1;
}
/**
* Advances the position until after the next newline character. If the line
* is terminated by "\r\n", the '\n' must be consumed as whitespace by the
* caller.
*/
private void skipToEndOfLine() {
for (; pos < in.length(); pos++) {
char c = in.charAt(pos);
if (c == '\r' || c == '\n') {
pos++;
break;
}
}
}
/**
* Returns the string up to but not including {@code quote}, unescaping any
* character escape sequences encountered along the way. The opening quote
* should have already been read. This consumes the closing quote, but does
* not include it in the returned string.
*
* @param quote either ' or ".
* @throws NumberFormatException if any unicode escape sequences are
* malformed.
*/
public String nextString(char quote) throws JSONException {
/*
* For strings that are free of escape sequences, we can just extract
* the result as a substring of the input. But if we encounter an escape
* sequence, we need to use a StringBuilder to compose the result.
*/
StringBuilder builder = null;
/* the index of the first character not yet appended to the builder. */
int start = pos;
while (pos < in.length()) {
int c = in.charAt(pos++);
if (c == quote) {
if (builder == null) {
// a new string avoids leaking memory
return new String(in.substring(start, pos - 1));
} else {
builder.append(in, start, pos - 1);
return builder.toString();
}
}
if (c == '\\') {
if (pos == in.length()) {
throw syntaxError("Unterminated escape sequence");
}
if (builder == null) {
builder = new StringBuilder();
}
builder.append(in, start, pos - 1);
builder.append(readEscapeCharacter());
start = pos;
}
}
throw syntaxError("Unterminated string");
}
/**
* Unescapes the character identified by the character or characters that
* immediately follow a backslash. The backslash '\' should have already
* been read. This supports both unicode escapes "u000A" and two-character
* escapes "\n".
*
* @throws NumberFormatException if any unicode escape sequences are
* malformed.
*/
private char readEscapeCharacter() throws JSONException {
char escaped = in.charAt(pos++);
switch (escaped) {
case 'u':
if (pos + 4 > in.length()) {
throw syntaxError("Unterminated escape sequence");
}
String hex = in.substring(pos, pos + 4);
pos += 4;
return (char) Integer.parseInt(hex, 16);
case 't':
return '\t';
case 'b':
return '\b';
case 'n':
return '\n';
case 'r':
return '\r';
case 'f':
return '\f';
case '\'':
case '"':
case '\\':
default:
return escaped;
}
}
/**
* Reads a null, boolean, numeric or unquoted string literal value. Numeric
* values will be returned as an Integer, Long, or Double, in that order of
* preference.
*/
private Object readLiteral() throws JSONException {
String literal = nextToInternal("{}[]/\\:,=;# \t\f");
if (literal.length() == 0) {
throw syntaxError("Expected literal value");
} else if ("null".equalsIgnoreCase(literal)) {
return JSONObject.NULL;
} else if ("true".equalsIgnoreCase(literal)) {
return Boolean.TRUE;
} else if ("false".equalsIgnoreCase(literal)) {
return Boolean.FALSE;
}
/* try to parse as an integral type... */
if (literal.indexOf('.') == -1) {
int base = 10;
String number = literal;
if (number.startsWith("0x") || number.startsWith("0X")) {
number = number.substring(2);
base = 16;
} else if (number.startsWith("0") && number.length() > 1) {
number = number.substring(1);
base = 8;
}
try {
long longValue = Long.parseLong(number, base);
if (longValue <= Integer.MAX_VALUE && longValue >= Integer.MIN_VALUE) {
return (int) longValue;
} else {
return longValue;
}
} catch (NumberFormatException e) {
/*
* This only happens for integral numbers greater than
* Long.MAX_VALUE, numbers in exponential form (5e-10) and
* unquoted strings. Fall through to try floating point.
*/
}
}
/* ...next try to parse as a floating point... */
try {
return Double.valueOf(literal);
} catch (NumberFormatException ignored) {
}
/* ... finally give up. We have an unquoted string */
return new String(literal); // a new string avoids leaking memory
}
/**
* Returns the string up to but not including any of the given characters or
* a newline character. This does not consume the excluded character.
*/
private String nextToInternal(String excluded) {
int start = pos;
for (; pos < in.length(); pos++) {
char c = in.charAt(pos);
if (c == '\r' || c == '\n' || excluded.indexOf(c) != -1) {
return in.substring(start, pos);
}
}
return in.substring(start);
}
/**
* Reads a sequence of key/value pairs and the trailing closing brace '}' of
* an object. The opening brace '{' should have already been read.
*/
private JSONObject readObject() throws JSONException {
JSONObject result = new JSONObject();
/* Peek to see if this is the empty object. */
int first = nextCleanInternal();
if (first == '}') {
return result;
} else if (first != -1) {
pos--;
}
while (true) {
Object name = nextValue();
if (!(name instanceof String)) {
if (name == null) {
throw syntaxError("Names cannot be null");
} else {
throw syntaxError("Names must be strings, but " + name
+ " is of type " + name.getClass().getName());
}
}
/*
* Expect the name/value separator to be either a colon ':', an
* equals sign '=', or an arrow "=>". The last two are bogus but we
* include them because that's what the original implementation did.
*/
int separator = nextCleanInternal();
if (separator != ':' && separator != '=') {
throw syntaxError("Expected ':' after " + name);
}
if (pos < in.length() && in.charAt(pos) == '>') {
pos++;
}
result.put((String) name, nextValue());
switch (nextCleanInternal()) {
case '}':
return result;
case ';':
case ',':
continue;
default:
throw syntaxError("Unterminated object");
}
}
}
/**
* Reads a sequence of values and the trailing closing brace ']' of an
* array. The opening brace '[' should have already been read. Note that
* "[]" yields an empty array, but "[,]" returns a two-element array
* equivalent to "[null,null]".
*/
private JSONArray readArray() throws JSONException {
JSONArray result = new JSONArray();
/* to cover input that ends with ",]". */
boolean hasTrailingSeparator = false;
while (true) {
switch (nextCleanInternal()) {
case -1:
throw syntaxError("Unterminated array");
case ']':
if (hasTrailingSeparator) {
result.put(null);
}
return result;
case ',':
case ';':
/* A separator without a value first means "null". */
result.put(null);
hasTrailingSeparator = true;
continue;
default:
pos--;
}
result.put(nextValue());
switch (nextCleanInternal()) {
case ']':
return result;
case ',':
case ';':
hasTrailingSeparator = true;
continue;
default:
throw syntaxError("Unterminated array");
}
}
}
/**
* Returns an exception containing the given message plus the current
* position and the entire input string.
*/
public JSONException syntaxError(String message) {
return new JSONException(message + this);
}
/**
* Returns the current position and the entire input string.
*/
@Override public String toString() {
// consistent with the original implementation
return " at character " + pos + " of " + in;
}
/*
* Legacy APIs.
*
* None of the methods below are on the critical path of parsing JSON
* documents. They exist only because they were exposed by the original
* implementation and may be used by some clients.
*/
/**
* Returns true until the input has been exhausted.
*/
public boolean more() {
return pos < in.length();
}
/**
* Returns the next available character, or the null character '\0' if all
* input has been exhausted. The return value of this method is ambiguous
* for JSON strings that contain the character '\0'.
*/
public char next() {
return pos < in.length() ? in.charAt(pos++) : '\0';
}
/**
* Returns the next available character if it equals {@code c}. Otherwise an
* exception is thrown.
*/
public char next(char c) throws JSONException {
char result = next();
if (result != c) {
throw syntaxError("Expected " + c + " but was " + result);
}
return result;
}
/**
* Returns the next character that is not whitespace and does not belong to
* a comment. If the input is exhausted before such a character can be
* found, the null character '\0' is returned. The return value of this
* method is ambiguous for JSON strings that contain the character '\0'.
*/
public char nextClean() throws JSONException {
int nextCleanInt = nextCleanInternal();
return nextCleanInt == -1 ? '\0' : (char) nextCleanInt;
}
/**
* Returns the next {@code length} characters of the input.
*
*
The returned string shares its backing character array with this
* tokener's input string. If a reference to the returned string may be held
* indefinitely, you should use {@code new String(result)} to copy it first
* to avoid memory leaks.
*
* @throws JSONException if the remaining input is not long enough to
* satisfy this request.
*/
public String next(int length) throws JSONException {
if (pos + length > in.length()) {
throw syntaxError(length + " is out of bounds");
}
String result = in.substring(pos, pos + length);
pos += length;
return result;
}
/**
* Returns the {@link String#trim trimmed} string holding the characters up
* to but not including the first of:
*
* any character in {@code excluded}
* a newline character '\n'
* a carriage return '\r'
*
*
* The returned string shares its backing character array with this
* tokener's input string. If a reference to the returned string may be held
* indefinitely, you should use {@code new String(result)} to copy it first
* to avoid memory leaks.
*
* @return a possibly-empty string
*/
public String nextTo(String excluded) {
if (excluded == null) {
throw new NullPointerException("excluded == null");
}
return nextToInternal(excluded).trim();
}
/**
* Equivalent to {@code nextTo(String.valueOf(excluded))}.
*/
public String nextTo(char excluded) {
return nextToInternal(String.valueOf(excluded)).trim();
}
/**
* Advances past all input up to and including the next occurrence of
* {@code thru}. If the remaining input doesn't contain {@code thru}, the
* input is exhausted.
*/
public void skipPast(String thru) {
int thruStart = in.indexOf(thru, pos);
pos = thruStart == -1 ? in.length() : (thruStart + thru.length());
}
/**
* Advances past all input up to but not including the next occurrence of
* {@code to}. If the remaining input doesn't contain {@code to}, the input
* is unchanged.
*/
public char skipTo(char to) {
int index = in.indexOf(to, pos);
if (index != -1) {
pos = index;
return to;
} else {
return '\0';
}
}
/**
* Unreads the most recent character of input. If no input characters have
* been read, the input is unchanged.
*/
public void back() {
if (--pos == -1) {
pos = 0;
}
}
/**
* Returns the integer [0..15] value for the given hex character, or -1
* for non-hex input.
*
* @param hex a character in the ranges [0-9], [A-F] or [a-f]. Any other
* character will yield a -1 result.
*/
public static int dehexchar(char hex) {
if (hex >= '0' && hex <= '9') {
return hex - '0';
} else if (hex >= 'A' && hex <= 'F') {
return hex - 'A' + 10;
} else if (hex >= 'a' && hex <= 'f') {
return hex - 'a' + 10;
} else {
return -1;
}
}
}
libandroid-json-org-java-20121204-20090211/src/test/ 0000775 0000000 0000000 00000000000 12071360135 0021171 5 ustar 00root root 0000000 0000000 libandroid-json-org-java-20121204-20090211/src/test/java/ 0000775 0000000 0000000 00000000000 12071360135 0022112 5 ustar 00root root 0000000 0000000 libandroid-json-org-java-20121204-20090211/src/test/java/org/ 0000775 0000000 0000000 00000000000 12071360135 0022701 5 ustar 00root root 0000000 0000000 libandroid-json-org-java-20121204-20090211/src/test/java/org/json/ 0000775 0000000 0000000 00000000000 12071360135 0023652 5 ustar 00root root 0000000 0000000 libandroid-json-org-java-20121204-20090211/src/test/java/org/json/JSONArrayTest.java 0000664 0000000 0000000 00000044457 12071360135 0027143 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.json;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import junit.framework.TestCase;
/**
* This black box test was written without inspecting the non-free org.json sourcecode.
*/
public class JSONArrayTest extends TestCase {
public void testEmptyArray() throws JSONException {
JSONArray array = new JSONArray();
assertEquals(0, array.length());
assertEquals("", array.join(" AND "));
try {
array.get(0);
fail();
} catch (JSONException e) {
}
try {
array.getBoolean(0);
fail();
} catch (JSONException e) {
}
assertEquals("[]", array.toString());
assertEquals("[]", array.toString(4));
// out of bounds is co-opted with defaulting
assertTrue(array.isNull(0));
assertNull(array.opt(0));
assertFalse(array.optBoolean(0));
assertTrue(array.optBoolean(0, true));
// bogus (but documented) behaviour: returns null rather than an empty object!
assertNull(array.toJSONObject(new JSONArray()));
}
public void testEqualsAndHashCode() throws JSONException {
JSONArray a = new JSONArray();
JSONArray b = new JSONArray();
assertTrue(a.equals(b));
assertEquals("equals() not consistent with hashCode()", a.hashCode(), b.hashCode());
a.put(true);
a.put(false);
b.put(true);
b.put(false);
assertTrue(a.equals(b));
assertEquals(a.hashCode(), b.hashCode());
b.put(true);
assertFalse(a.equals(b));
assertTrue(a.hashCode() != b.hashCode());
}
public void testBooleans() throws JSONException {
JSONArray array = new JSONArray();
array.put(true);
array.put(false);
array.put(2, false);
array.put(3, false);
array.put(2, true);
assertEquals("[true,false,true,false]", array.toString());
assertEquals(4, array.length());
assertEquals(Boolean.TRUE, array.get(0));
assertEquals(Boolean.FALSE, array.get(1));
assertEquals(Boolean.TRUE, array.get(2));
assertEquals(Boolean.FALSE, array.get(3));
assertFalse(array.isNull(0));
assertFalse(array.isNull(1));
assertFalse(array.isNull(2));
assertFalse(array.isNull(3));
assertEquals(true, array.optBoolean(0));
assertEquals(false, array.optBoolean(1, true));
assertEquals(true, array.optBoolean(2, false));
assertEquals(false, array.optBoolean(3));
assertEquals("true", array.getString(0));
assertEquals("false", array.getString(1));
assertEquals("true", array.optString(2));
assertEquals("false", array.optString(3, "x"));
assertEquals("[\n true,\n false,\n true,\n false\n]", array.toString(5));
JSONArray other = new JSONArray();
other.put(true);
other.put(false);
other.put(true);
other.put(false);
assertTrue(array.equals(other));
other.put(true);
assertFalse(array.equals(other));
other = new JSONArray();
other.put("true");
other.put("false");
other.put("truE");
other.put("FALSE");
assertFalse(array.equals(other));
assertFalse(other.equals(array));
assertEquals(true, other.getBoolean(0));
assertEquals(false, other.optBoolean(1, true));
assertEquals(true, other.optBoolean(2));
assertEquals(false, other.getBoolean(3));
}
// http://code.google.com/p/android/issues/detail?id=16411
public void testCoerceStringToBoolean() throws JSONException {
JSONArray array = new JSONArray();
array.put("maybe");
try {
array.getBoolean(0);
fail();
} catch (JSONException expected) {
}
assertEquals(false, array.optBoolean(0));
assertEquals(true, array.optBoolean(0, true));
}
public void testNulls() throws JSONException {
JSONArray array = new JSONArray();
array.put(3, null);
array.put(0, JSONObject.NULL);
assertEquals(4, array.length());
assertEquals("[null,null,null,null]", array.toString());
// there's 2 ways to represent null; each behaves differently!
assertEquals(JSONObject.NULL, array.get(0));
try {
array.get(1);
fail();
} catch (JSONException e) {
}
try {
array.get(2);
fail();
} catch (JSONException e) {
}
try {
array.get(3);
fail();
} catch (JSONException e) {
}
assertEquals(JSONObject.NULL, array.opt(0));
assertEquals(null, array.opt(1));
assertEquals(null, array.opt(2));
assertEquals(null, array.opt(3));
assertTrue(array.isNull(0));
assertTrue(array.isNull(1));
assertTrue(array.isNull(2));
assertTrue(array.isNull(3));
assertEquals("null", array.optString(0));
assertEquals("", array.optString(1));
assertEquals("", array.optString(2));
assertEquals("", array.optString(3));
}
/**
* Our behaviour is questioned by this bug:
* http://code.google.com/p/android/issues/detail?id=7257
*/
public void testParseNullYieldsJSONObjectNull() throws JSONException {
JSONArray array = new JSONArray("[\"null\",null]");
array.put(null);
assertEquals("null", array.get(0));
assertEquals(JSONObject.NULL, array.get(1));
try {
array.get(2);
fail();
} catch (JSONException e) {
}
assertEquals("null", array.getString(0));
assertEquals("null", array.getString(1));
try {
array.getString(2);
fail();
} catch (JSONException e) {
}
}
public void testNumbers() throws JSONException {
JSONArray array = new JSONArray();
array.put(Double.MIN_VALUE);
array.put(9223372036854775806L);
array.put(Double.MAX_VALUE);
array.put(-0d);
assertEquals(4, array.length());
// toString() and getString(int) return different values for -0d
assertEquals("[4.9E-324,9223372036854775806,1.7976931348623157E308,-0]", array.toString());
assertEquals(Double.MIN_VALUE, array.get(0));
assertEquals(9223372036854775806L, array.get(1));
assertEquals(Double.MAX_VALUE, array.get(2));
assertEquals(-0d, array.get(3));
assertEquals(Double.MIN_VALUE, array.getDouble(0));
assertEquals(9.223372036854776E18, array.getDouble(1));
assertEquals(Double.MAX_VALUE, array.getDouble(2));
assertEquals(-0d, array.getDouble(3));
assertEquals(0, array.getLong(0));
assertEquals(9223372036854775806L, array.getLong(1));
assertEquals(Long.MAX_VALUE, array.getLong(2));
assertEquals(0, array.getLong(3));
assertEquals(0, array.getInt(0));
assertEquals(-2, array.getInt(1));
assertEquals(Integer.MAX_VALUE, array.getInt(2));
assertEquals(0, array.getInt(3));
assertEquals(Double.MIN_VALUE, array.opt(0));
assertEquals(Double.MIN_VALUE, array.optDouble(0));
assertEquals(0, array.optLong(0, 1L));
assertEquals(0, array.optInt(0, 1));
assertEquals("4.9E-324", array.getString(0));
assertEquals("9223372036854775806", array.getString(1));
assertEquals("1.7976931348623157E308", array.getString(2));
assertEquals("-0.0", array.getString(3));
JSONArray other = new JSONArray();
other.put(Double.MIN_VALUE);
other.put(9223372036854775806L);
other.put(Double.MAX_VALUE);
other.put(-0d);
assertTrue(array.equals(other));
other.put(0, 0L);
assertFalse(array.equals(other));
}
public void testStrings() throws JSONException {
JSONArray array = new JSONArray();
array.put("true");
array.put("5.5");
array.put("9223372036854775806");
array.put("null");
array.put("5\"8' tall");
assertEquals(5, array.length());
assertEquals("[\"true\",\"5.5\",\"9223372036854775806\",\"null\",\"5\\\"8' tall\"]",
array.toString());
// although the documentation doesn't mention it, join() escapes text and wraps
// strings in quotes
assertEquals("\"true\" \"5.5\" \"9223372036854775806\" \"null\" \"5\\\"8' tall\"",
array.join(" "));
assertEquals("true", array.get(0));
assertEquals("null", array.getString(3));
assertEquals("5\"8' tall", array.getString(4));
assertEquals("true", array.opt(0));
assertEquals("5.5", array.optString(1));
assertEquals("9223372036854775806", array.optString(2, null));
assertEquals("null", array.optString(3, "-1"));
assertFalse(array.isNull(0));
assertFalse(array.isNull(3));
assertEquals(true, array.getBoolean(0));
assertEquals(true, array.optBoolean(0));
assertEquals(true, array.optBoolean(0, false));
assertEquals(0, array.optInt(0));
assertEquals(-2, array.optInt(0, -2));
assertEquals(5.5d, array.getDouble(1));
assertEquals(5L, array.getLong(1));
assertEquals(5, array.getInt(1));
assertEquals(5, array.optInt(1, 3));
// The last digit of the string is a 6 but getLong returns a 7. It's probably parsing as a
// double and then converting that to a long. This is consistent with JavaScript.
assertEquals(9223372036854775807L, array.getLong(2));
assertEquals(9.223372036854776E18, array.getDouble(2));
assertEquals(Integer.MAX_VALUE, array.getInt(2));
assertFalse(array.isNull(3));
try {
array.getDouble(3);
fail();
} catch (JSONException e) {
}
assertEquals(Double.NaN, array.optDouble(3));
assertEquals(-1.0d, array.optDouble(3, -1.0d));
}
public void testJoin() throws JSONException {
JSONArray array = new JSONArray();
array.put(null);
assertEquals("null", array.join(" & "));
array.put("\"");
assertEquals("null & \"\\\"\"", array.join(" & "));
array.put(5);
assertEquals("null & \"\\\"\" & 5", array.join(" & "));
array.put(true);
assertEquals("null & \"\\\"\" & 5 & true", array.join(" & "));
array.put(new JSONArray(Arrays.asList(true, false)));
assertEquals("null & \"\\\"\" & 5 & true & [true,false]", array.join(" & "));
array.put(new JSONObject(Collections.singletonMap("x", 6)));
assertEquals("null & \"\\\"\" & 5 & true & [true,false] & {\"x\":6}", array.join(" & "));
}
public void testJoinWithNull() throws JSONException {
JSONArray array = new JSONArray(Arrays.asList(5, 6));
assertEquals("5null6", array.join(null));
}
public void testJoinWithSpecialCharacters() throws JSONException {
JSONArray array = new JSONArray(Arrays.asList(5, 6));
assertEquals("5\"6", array.join("\""));
}
public void testToJSONObject() throws JSONException {
JSONArray keys = new JSONArray();
keys.put("a");
keys.put("b");
JSONArray values = new JSONArray();
values.put(5.5d);
values.put(false);
JSONObject object = values.toJSONObject(keys);
assertEquals(5.5d, object.get("a"));
assertEquals(false, object.get("b"));
keys.put(0, "a");
values.put(0, 11.0d);
assertEquals(5.5d, object.get("a"));
}
public void testToJSONObjectWithNulls() throws JSONException {
JSONArray keys = new JSONArray();
keys.put("a");
keys.put("b");
JSONArray values = new JSONArray();
values.put(5.5d);
values.put(null);
// null values are stripped!
JSONObject object = values.toJSONObject(keys);
assertEquals(1, object.length());
assertFalse(object.has("b"));
assertEquals("{\"a\":5.5}", object.toString());
}
public void testToJSONObjectMoreNamesThanValues() throws JSONException {
JSONArray keys = new JSONArray();
keys.put("a");
keys.put("b");
JSONArray values = new JSONArray();
values.put(5.5d);
JSONObject object = values.toJSONObject(keys);
assertEquals(1, object.length());
assertEquals(5.5d, object.get("a"));
}
public void testToJSONObjectMoreValuesThanNames() throws JSONException {
JSONArray keys = new JSONArray();
keys.put("a");
JSONArray values = new JSONArray();
values.put(5.5d);
values.put(11.0d);
JSONObject object = values.toJSONObject(keys);
assertEquals(1, object.length());
assertEquals(5.5d, object.get("a"));
}
public void testToJSONObjectNullKey() throws JSONException {
JSONArray keys = new JSONArray();
keys.put(JSONObject.NULL);
JSONArray values = new JSONArray();
values.put(5.5d);
JSONObject object = values.toJSONObject(keys);
assertEquals(1, object.length());
assertEquals(5.5d, object.get("null"));
}
public void testPutUnsupportedNumbers() throws JSONException {
JSONArray array = new JSONArray();
try {
array.put(Double.NaN);
fail();
} catch (JSONException e) {
}
try {
array.put(0, Double.NEGATIVE_INFINITY);
fail();
} catch (JSONException e) {
}
try {
array.put(0, Double.POSITIVE_INFINITY);
fail();
} catch (JSONException e) {
}
}
public void testPutUnsupportedNumbersAsObject() throws JSONException {
JSONArray array = new JSONArray();
array.put(Double.valueOf(Double.NaN));
array.put(Double.valueOf(Double.NEGATIVE_INFINITY));
array.put(Double.valueOf(Double.POSITIVE_INFINITY));
assertEquals(null, array.toString());
}
/**
* Although JSONArray is usually defensive about which numbers it accepts,
* it doesn't check inputs in its constructor.
*/
public void testCreateWithUnsupportedNumbers() throws JSONException {
JSONArray array = new JSONArray(Arrays.asList(5.5, Double.NaN));
assertEquals(2, array.length());
assertEquals(5.5, array.getDouble(0));
assertEquals(Double.NaN, array.getDouble(1));
}
public void testToStringWithUnsupportedNumbers() throws JSONException {
// when the array contains an unsupported number, toString returns null!
JSONArray array = new JSONArray(Arrays.asList(5.5, Double.NaN));
assertNull(array.toString());
}
public void testListConstructorCopiesContents() throws JSONException {
List contents = Arrays.asList(5);
JSONArray array = new JSONArray(contents);
contents.set(0, 10);
assertEquals(5, array.get(0));
}
public void testTokenerConstructor() throws JSONException {
JSONArray object = new JSONArray(new JSONTokener("[false]"));
assertEquals(1, object.length());
assertEquals(false, object.get(0));
}
public void testTokenerConstructorWrongType() throws JSONException {
try {
new JSONArray(new JSONTokener("{\"foo\": false}"));
fail();
} catch (JSONException e) {
}
}
public void testTokenerConstructorNull() throws JSONException {
try {
new JSONArray((JSONTokener) null);
fail();
} catch (NullPointerException e) {
}
}
public void testTokenerConstructorParseFail() {
try {
new JSONArray(new JSONTokener("["));
fail();
} catch (JSONException e) {
} catch (StackOverflowError e) {
fail("Stack overflowed on input: \"[\"");
}
}
public void testStringConstructor() throws JSONException {
JSONArray object = new JSONArray("[false]");
assertEquals(1, object.length());
assertEquals(false, object.get(0));
}
public void testStringConstructorWrongType() throws JSONException {
try {
new JSONArray("{\"foo\": false}");
fail();
} catch (JSONException e) {
}
}
public void testStringConstructorNull() throws JSONException {
try {
new JSONArray((String) null);
fail();
} catch (NullPointerException e) {
}
}
public void testStringConstructorParseFail() {
try {
new JSONArray("[");
fail();
} catch (JSONException e) {
} catch (StackOverflowError e) {
fail("Stack overflowed on input: \"[\"");
}
}
public void testCreate() throws JSONException {
JSONArray array = new JSONArray(Arrays.asList(5.5, true));
assertEquals(2, array.length());
assertEquals(5.5, array.getDouble(0));
assertEquals(true, array.get(1));
assertEquals("[5.5,true]", array.toString());
}
public void testAccessOutOfBounds() throws JSONException {
JSONArray array = new JSONArray();
array.put("foo");
assertEquals(null, array.opt(3));
assertEquals(null, array.opt(-3));
assertEquals("", array.optString(3));
assertEquals("", array.optString(-3));
try {
array.get(3);
fail();
} catch (JSONException e) {
}
try {
array.get(-3);
fail();
} catch (JSONException e) {
}
try {
array.getString(3);
fail();
} catch (JSONException e) {
}
try {
array.getString(-3);
fail();
} catch (JSONException e) {
}
}
}
libandroid-json-org-java-20121204-20090211/src/test/java/org/json/JSONObjectTest.java 0000664 0000000 0000000 00000100743 12071360135 0027262 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.json;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import junit.framework.TestCase;
/**
* This black box test was written without inspecting the non-free org.json sourcecode.
*/
public class JSONObjectTest extends TestCase {
public void testEmptyObject() throws JSONException {
JSONObject object = new JSONObject();
assertEquals(0, object.length());
// bogus (but documented) behaviour: returns null rather than the empty object!
assertNull(object.names());
// returns null rather than an empty array!
assertNull(object.toJSONArray(new JSONArray()));
assertEquals("{}", object.toString());
assertEquals("{}", object.toString(5));
try {
object.get("foo");
fail();
} catch (JSONException e) {
}
try {
object.getBoolean("foo");
fail();
} catch (JSONException e) {
}
try {
object.getDouble("foo");
fail();
} catch (JSONException e) {
}
try {
object.getInt("foo");
fail();
} catch (JSONException e) {
}
try {
object.getJSONArray("foo");
fail();
} catch (JSONException e) {
}
try {
object.getJSONObject("foo");
fail();
} catch (JSONException e) {
}
try {
object.getLong("foo");
fail();
} catch (JSONException e) {
}
try {
object.getString("foo");
fail();
} catch (JSONException e) {
}
assertFalse(object.has("foo"));
assertTrue(object.isNull("foo")); // isNull also means "is not present"
assertNull(object.opt("foo"));
assertEquals(false, object.optBoolean("foo"));
assertEquals(true, object.optBoolean("foo", true));
assertEquals(Double.NaN, object.optDouble("foo"));
assertEquals(5.0, object.optDouble("foo", 5.0));
assertEquals(0, object.optInt("foo"));
assertEquals(5, object.optInt("foo", 5));
assertEquals(null, object.optJSONArray("foo"));
assertEquals(null, object.optJSONObject("foo"));
assertEquals(0, object.optLong("foo"));
assertEquals(Long.MAX_VALUE-1, object.optLong("foo", Long.MAX_VALUE-1));
assertEquals("", object.optString("foo")); // empty string is default!
assertEquals("bar", object.optString("foo", "bar"));
assertNull(object.remove("foo"));
}
public void testEqualsAndHashCode() throws JSONException {
JSONObject a = new JSONObject();
JSONObject b = new JSONObject();
// JSON object doesn't override either equals or hashCode (!)
assertFalse(a.equals(b));
assertEquals(a.hashCode(), System.identityHashCode(a));
}
public void testGet() throws JSONException {
JSONObject object = new JSONObject();
Object value = new Object();
object.put("foo", value);
object.put("bar", new Object());
object.put("baz", new Object());
assertSame(value, object.get("foo"));
try {
object.get("FOO");
fail();
} catch (JSONException e) {
}
try {
object.put(null, value);
fail();
} catch (JSONException e) {
}
try {
object.get(null);
fail();
} catch (JSONException e) {
}
}
public void testPut() throws JSONException {
JSONObject object = new JSONObject();
assertSame(object, object.put("foo", true));
object.put("foo", false);
assertEquals(false, object.get("foo"));
object.put("foo", 5.0d);
assertEquals(5.0d, object.get("foo"));
object.put("foo", 0);
assertEquals(0, object.get("foo"));
object.put("bar", Long.MAX_VALUE - 1);
assertEquals(Long.MAX_VALUE - 1, object.get("bar"));
object.put("baz", "x");
assertEquals("x", object.get("baz"));
object.put("bar", JSONObject.NULL);
assertSame(JSONObject.NULL, object.get("bar"));
}
public void testPutNullRemoves() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", "bar");
object.put("foo", null);
assertEquals(0, object.length());
assertFalse(object.has("foo"));
try {
object.get("foo");
fail();
} catch (JSONException e) {
}
}
public void testPutOpt() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", "bar");
object.putOpt("foo", null);
assertEquals("bar", object.get("foo"));
object.putOpt(null, null);
assertEquals(1, object.length());
object.putOpt(null, "bar");
assertEquals(1, object.length());
}
public void testPutOptUnsupportedNumbers() throws JSONException {
JSONObject object = new JSONObject();
try {
object.putOpt("foo", Double.NaN);
fail();
} catch (JSONException e) {
}
try {
object.putOpt("foo", Double.NEGATIVE_INFINITY);
fail();
} catch (JSONException e) {
}
try {
object.putOpt("foo", Double.POSITIVE_INFINITY);
fail();
} catch (JSONException e) {
}
}
public void testRemove() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", "bar");
assertEquals(null, object.remove(null));
assertEquals(null, object.remove(""));
assertEquals(null, object.remove("bar"));
assertEquals("bar", object.remove("foo"));
assertEquals(null, object.remove("foo"));
}
public void testBooleans() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", true);
object.put("bar", false);
object.put("baz", "true");
object.put("quux", "false");
assertEquals(4, object.length());
assertEquals(true, object.getBoolean("foo"));
assertEquals(false, object.getBoolean("bar"));
assertEquals(true, object.getBoolean("baz"));
assertEquals(false, object.getBoolean("quux"));
assertFalse(object.isNull("foo"));
assertFalse(object.isNull("quux"));
assertTrue(object.has("foo"));
assertTrue(object.has("quux"));
assertFalse(object.has("missing"));
assertEquals(true, object.optBoolean("foo"));
assertEquals(false, object.optBoolean("bar"));
assertEquals(true, object.optBoolean("baz"));
assertEquals(false, object.optBoolean("quux"));
assertEquals(false, object.optBoolean("missing"));
assertEquals(true, object.optBoolean("foo", true));
assertEquals(false, object.optBoolean("bar", true));
assertEquals(true, object.optBoolean("baz", true));
assertEquals(false, object.optBoolean("quux", true));
assertEquals(true, object.optBoolean("missing", true));
object.put("foo", "truE");
object.put("bar", "FALSE");
assertEquals(true, object.getBoolean("foo"));
assertEquals(false, object.getBoolean("bar"));
assertEquals(true, object.optBoolean("foo"));
assertEquals(false, object.optBoolean("bar"));
assertEquals(true, object.optBoolean("foo", false));
assertEquals(false, object.optBoolean("bar", false));
}
// http://code.google.com/p/android/issues/detail?id=16411
public void testCoerceStringToBoolean() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", "maybe");
try {
object.getBoolean("foo");
fail();
} catch (JSONException expected) {
}
assertEquals(false, object.optBoolean("foo"));
assertEquals(true, object.optBoolean("foo", true));
}
public void testNumbers() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", Double.MIN_VALUE);
object.put("bar", 9223372036854775806L);
object.put("baz", Double.MAX_VALUE);
object.put("quux", -0d);
assertEquals(4, object.length());
String toString = object.toString();
assertTrue(toString, toString.contains("\"foo\":4.9E-324"));
assertTrue(toString, toString.contains("\"bar\":9223372036854775806"));
assertTrue(toString, toString.contains("\"baz\":1.7976931348623157E308"));
// toString() and getString() return different values for -0d!
assertTrue(toString, toString.contains("\"quux\":-0}") // no trailing decimal point
|| toString.contains("\"quux\":-0,"));
assertEquals(Double.MIN_VALUE, object.get("foo"));
assertEquals(9223372036854775806L, object.get("bar"));
assertEquals(Double.MAX_VALUE, object.get("baz"));
assertEquals(-0d, object.get("quux"));
assertEquals(Double.MIN_VALUE, object.getDouble("foo"));
assertEquals(9.223372036854776E18, object.getDouble("bar"));
assertEquals(Double.MAX_VALUE, object.getDouble("baz"));
assertEquals(-0d, object.getDouble("quux"));
assertEquals(0, object.getLong("foo"));
assertEquals(9223372036854775806L, object.getLong("bar"));
assertEquals(Long.MAX_VALUE, object.getLong("baz"));
assertEquals(0, object.getLong("quux"));
assertEquals(0, object.getInt("foo"));
assertEquals(-2, object.getInt("bar"));
assertEquals(Integer.MAX_VALUE, object.getInt("baz"));
assertEquals(0, object.getInt("quux"));
assertEquals(Double.MIN_VALUE, object.opt("foo"));
assertEquals(9223372036854775806L, object.optLong("bar"));
assertEquals(Double.MAX_VALUE, object.optDouble("baz"));
assertEquals(0, object.optInt("quux"));
assertEquals(Double.MIN_VALUE, object.opt("foo"));
assertEquals(9223372036854775806L, object.optLong("bar"));
assertEquals(Double.MAX_VALUE, object.optDouble("baz"));
assertEquals(0, object.optInt("quux"));
assertEquals(Double.MIN_VALUE, object.optDouble("foo", 5.0d));
assertEquals(9223372036854775806L, object.optLong("bar", 1L));
assertEquals(Long.MAX_VALUE, object.optLong("baz", 1L));
assertEquals(0, object.optInt("quux", -1));
assertEquals("4.9E-324", object.getString("foo"));
assertEquals("9223372036854775806", object.getString("bar"));
assertEquals("1.7976931348623157E308", object.getString("baz"));
assertEquals("-0.0", object.getString("quux"));
}
public void testFloats() throws JSONException {
JSONObject object = new JSONObject();
try {
object.put("foo", (Float) Float.NaN);
fail();
} catch (JSONException e) {
}
try {
object.put("foo", (Float) Float.NEGATIVE_INFINITY);
fail();
} catch (JSONException e) {
}
try {
object.put("foo", (Float) Float.POSITIVE_INFINITY);
fail();
} catch (JSONException e) {
}
}
public void testOtherNumbers() throws JSONException {
Number nan = new Number() {
public int intValue() {
throw new UnsupportedOperationException();
}
public long longValue() {
throw new UnsupportedOperationException();
}
public float floatValue() {
throw new UnsupportedOperationException();
}
public double doubleValue() {
return Double.NaN;
}
@Override public String toString() {
return "x";
}
};
JSONObject object = new JSONObject();
try {
object.put("foo", nan);
fail("Object.put() accepted a NaN (via a custom Number class)");
} catch (JSONException e) {
}
}
public void testForeignObjects() throws JSONException {
Object foreign = new Object() {
@Override public String toString() {
return "x";
}
};
// foreign object types are accepted and treated as Strings!
JSONObject object = new JSONObject();
object.put("foo", foreign);
assertEquals("{\"foo\":\"x\"}", object.toString());
}
public void testNullKeys() {
try {
new JSONObject().put(null, false);
fail();
} catch (JSONException e) {
}
try {
new JSONObject().put(null, 0.0d);
fail();
} catch (JSONException e) {
}
try {
new JSONObject().put(null, 5);
fail();
} catch (JSONException e) {
}
try {
new JSONObject().put(null, 5L);
fail();
} catch (JSONException e) {
}
try {
new JSONObject().put(null, "foo");
fail();
} catch (JSONException e) {
}
}
public void testStrings() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", "true");
object.put("bar", "5.5");
object.put("baz", "9223372036854775806");
object.put("quux", "null");
object.put("height", "5\"8' tall");
assertTrue(object.toString().contains("\"foo\":\"true\""));
assertTrue(object.toString().contains("\"bar\":\"5.5\""));
assertTrue(object.toString().contains("\"baz\":\"9223372036854775806\""));
assertTrue(object.toString().contains("\"quux\":\"null\""));
assertTrue(object.toString().contains("\"height\":\"5\\\"8' tall\""));
assertEquals("true", object.get("foo"));
assertEquals("null", object.getString("quux"));
assertEquals("5\"8' tall", object.getString("height"));
assertEquals("true", object.opt("foo"));
assertEquals("5.5", object.optString("bar"));
assertEquals("true", object.optString("foo", "x"));
assertFalse(object.isNull("foo"));
assertEquals(true, object.getBoolean("foo"));
assertEquals(true, object.optBoolean("foo"));
assertEquals(true, object.optBoolean("foo", false));
assertEquals(0, object.optInt("foo"));
assertEquals(-2, object.optInt("foo", -2));
assertEquals(5.5d, object.getDouble("bar"));
assertEquals(5L, object.getLong("bar"));
assertEquals(5, object.getInt("bar"));
assertEquals(5, object.optInt("bar", 3));
// The last digit of the string is a 6 but getLong returns a 7. It's probably parsing as a
// double and then converting that to a long. This is consistent with JavaScript.
assertEquals(9223372036854775807L, object.getLong("baz"));
assertEquals(9.223372036854776E18, object.getDouble("baz"));
assertEquals(Integer.MAX_VALUE, object.getInt("baz"));
assertFalse(object.isNull("quux"));
try {
object.getDouble("quux");
fail();
} catch (JSONException e) {
}
assertEquals(Double.NaN, object.optDouble("quux"));
assertEquals(-1.0d, object.optDouble("quux", -1.0d));
object.put("foo", "TRUE");
assertEquals(true, object.getBoolean("foo"));
}
public void testJSONObjects() throws JSONException {
JSONObject object = new JSONObject();
JSONArray a = new JSONArray();
JSONObject b = new JSONObject();
object.put("foo", a);
object.put("bar", b);
assertSame(a, object.getJSONArray("foo"));
assertSame(b, object.getJSONObject("bar"));
try {
object.getJSONObject("foo");
fail();
} catch (JSONException e) {
}
try {
object.getJSONArray("bar");
fail();
} catch (JSONException e) {
}
assertEquals(a, object.optJSONArray("foo"));
assertEquals(b, object.optJSONObject("bar"));
assertEquals(null, object.optJSONArray("bar"));
assertEquals(null, object.optJSONObject("foo"));
}
public void testNullCoercionToString() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", JSONObject.NULL);
assertEquals("null", object.getString("foo"));
}
public void testArrayCoercion() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", "[true]");
try {
object.getJSONArray("foo");
fail();
} catch (JSONException e) {
}
}
public void testObjectCoercion() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", "{}");
try {
object.getJSONObject("foo");
fail();
} catch (JSONException e) {
}
}
public void testAccumulateValueChecking() throws JSONException {
JSONObject object = new JSONObject();
try {
object.accumulate("foo", Double.NaN);
fail();
} catch (JSONException e) {
}
object.accumulate("foo", 1);
try {
object.accumulate("foo", Double.NaN);
fail();
} catch (JSONException e) {
}
object.accumulate("foo", 2);
try {
object.accumulate("foo", Double.NaN);
fail();
} catch (JSONException e) {
}
}
public void testToJSONArray() throws JSONException {
JSONObject object = new JSONObject();
Object value = new Object();
object.put("foo", true);
object.put("bar", 5.0d);
object.put("baz", -0.0d);
object.put("quux", value);
JSONArray names = new JSONArray();
names.put("baz");
names.put("quux");
names.put("foo");
JSONArray array = object.toJSONArray(names);
assertEquals(-0.0d, array.get(0));
assertEquals(value, array.get(1));
assertEquals(true, array.get(2));
object.put("foo", false);
assertEquals(true, array.get(2));
}
public void testToJSONArrayMissingNames() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", true);
object.put("bar", 5.0d);
object.put("baz", JSONObject.NULL);
JSONArray names = new JSONArray();
names.put("bar");
names.put("foo");
names.put("quux");
names.put("baz");
JSONArray array = object.toJSONArray(names);
assertEquals(4, array.length());
assertEquals(5.0d, array.get(0));
assertEquals(true, array.get(1));
try {
array.get(2);
fail();
} catch (JSONException e) {
}
assertEquals(JSONObject.NULL, array.get(3));
}
public void testToJSONArrayNull() throws JSONException {
JSONObject object = new JSONObject();
assertEquals(null, object.toJSONArray(null));
object.put("foo", 5);
try {
object.toJSONArray(null);
} catch (JSONException e) {
}
}
public void testToJSONArrayEndsUpEmpty() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", 5);
JSONArray array = new JSONArray();
array.put("bar");
assertEquals(1, object.toJSONArray(array).length());
}
public void testToJSONArrayNonString() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", 5);
object.put("null", 10);
object.put("false", 15);
JSONArray names = new JSONArray();
names.put(JSONObject.NULL);
names.put(false);
names.put("foo");
// array elements are converted to strings to do name lookups on the map!
JSONArray array = object.toJSONArray(names);
assertEquals(3, array.length());
assertEquals(10, array.get(0));
assertEquals(15, array.get(1));
assertEquals(5, array.get(2));
}
public void testPutUnsupportedNumbers() throws JSONException {
JSONObject object = new JSONObject();
try {
object.put("foo", Double.NaN);
fail();
} catch (JSONException e) {
}
try {
object.put("foo", Double.NEGATIVE_INFINITY);
fail();
} catch (JSONException e) {
}
try {
object.put("foo", Double.POSITIVE_INFINITY);
fail();
} catch (JSONException e) {
}
}
public void testPutUnsupportedNumbersAsObjects() throws JSONException {
JSONObject object = new JSONObject();
try {
object.put("foo", (Double) Double.NaN);
fail();
} catch (JSONException e) {
}
try {
object.put("foo", (Double) Double.NEGATIVE_INFINITY);
fail();
} catch (JSONException e) {
}
try {
object.put("foo", (Double) Double.POSITIVE_INFINITY);
fail();
} catch (JSONException e) {
}
}
/**
* Although JSONObject is usually defensive about which numbers it accepts,
* it doesn't check inputs in its constructor.
*/
public void testCreateWithUnsupportedNumbers() throws JSONException {
Map contents = new HashMap();
contents.put("foo", Double.NaN);
contents.put("bar", Double.NEGATIVE_INFINITY);
contents.put("baz", Double.POSITIVE_INFINITY);
JSONObject object = new JSONObject(contents);
assertEquals(Double.NaN, object.get("foo"));
assertEquals(Double.NEGATIVE_INFINITY, object.get("bar"));
assertEquals(Double.POSITIVE_INFINITY, object.get("baz"));
}
public void testToStringWithUnsupportedNumbers() {
// when the object contains an unsupported number, toString returns null!
JSONObject object = new JSONObject(Collections.singletonMap("foo", Double.NaN));
assertEquals(null, object.toString());
}
public void testMapConstructorCopiesContents() throws JSONException {
Map contents = new HashMap();
contents.put("foo", 5);
JSONObject object = new JSONObject(contents);
contents.put("foo", 10);
assertEquals(5, object.get("foo"));
}
public void testMapConstructorWithBogusEntries() {
Map contents = new HashMap();
contents.put(5, 5);
try {
new JSONObject(contents);
fail("JSONObject constructor doesn't validate its input!");
} catch (Exception e) {
}
}
public void testTokenerConstructor() throws JSONException {
JSONObject object = new JSONObject(new JSONTokener("{\"foo\": false}"));
assertEquals(1, object.length());
assertEquals(false, object.get("foo"));
}
public void testTokenerConstructorWrongType() throws JSONException {
try {
new JSONObject(new JSONTokener("[\"foo\", false]"));
fail();
} catch (JSONException e) {
}
}
public void testTokenerConstructorNull() throws JSONException {
try {
new JSONObject((JSONTokener) null);
fail();
} catch (NullPointerException e) {
}
}
public void testTokenerConstructorParseFail() {
try {
new JSONObject(new JSONTokener("{"));
fail();
} catch (JSONException e) {
}
}
public void testStringConstructor() throws JSONException {
JSONObject object = new JSONObject("{\"foo\": false}");
assertEquals(1, object.length());
assertEquals(false, object.get("foo"));
}
public void testStringConstructorWrongType() throws JSONException {
try {
new JSONObject("[\"foo\", false]");
fail();
} catch (JSONException e) {
}
}
public void testStringConstructorNull() throws JSONException {
try {
new JSONObject((String) null);
fail();
} catch (NullPointerException e) {
}
}
public void testStringonstructorParseFail() {
try {
new JSONObject("{");
fail();
} catch (JSONException e) {
}
}
public void testCopyConstructor() throws JSONException {
JSONObject source = new JSONObject();
source.put("a", JSONObject.NULL);
source.put("b", false);
source.put("c", 5);
JSONObject copy = new JSONObject(source, new String[] { "a", "c" });
assertEquals(2, copy.length());
assertEquals(JSONObject.NULL, copy.get("a"));
assertEquals(5, copy.get("c"));
assertEquals(null, copy.opt("b"));
}
public void testCopyConstructorMissingName() throws JSONException {
JSONObject source = new JSONObject();
source.put("a", JSONObject.NULL);
source.put("b", false);
source.put("c", 5);
JSONObject copy = new JSONObject(source, new String[]{ "a", "c", "d" });
assertEquals(2, copy.length());
assertEquals(JSONObject.NULL, copy.get("a"));
assertEquals(5, copy.get("c"));
assertEquals(0, copy.optInt("b"));
}
public void testAccumulateMutatesInPlace() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", 5);
object.accumulate("foo", 6);
JSONArray array = object.getJSONArray("foo");
assertEquals("[5,6]", array.toString());
object.accumulate("foo", 7);
assertEquals("[5,6,7]", array.toString());
}
public void testAccumulateExistingArray() throws JSONException {
JSONArray array = new JSONArray();
JSONObject object = new JSONObject();
object.put("foo", array);
object.accumulate("foo", 5);
assertEquals("[5]", array.toString());
}
public void testAccumulatePutArray() throws JSONException {
JSONObject object = new JSONObject();
object.accumulate("foo", 5);
assertEquals("{\"foo\":5}", object.toString());
object.accumulate("foo", new JSONArray());
assertEquals("{\"foo\":[5,[]]}", object.toString());
}
public void testAccumulateNull() {
JSONObject object = new JSONObject();
try {
object.accumulate(null, 5);
fail();
} catch (JSONException e) {
}
}
public void testEmptyStringKey() throws JSONException {
JSONObject object = new JSONObject();
object.put("", 5);
assertEquals(5, object.get(""));
assertEquals("{\"\":5}", object.toString());
}
public void testNullValue() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", JSONObject.NULL);
object.put("bar", null);
// there are two ways to represent null; each behaves differently!
assertTrue(object.has("foo"));
assertFalse(object.has("bar"));
assertTrue(object.isNull("foo"));
assertTrue(object.isNull("bar"));
}
public void testHas() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", 5);
assertTrue(object.has("foo"));
assertFalse(object.has("bar"));
assertFalse(object.has(null));
}
public void testOptNull() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", "bar");
assertEquals(null, object.opt(null));
assertEquals(false, object.optBoolean(null));
assertEquals(Double.NaN, object.optDouble(null));
assertEquals(0, object.optInt(null));
assertEquals(0L, object.optLong(null));
assertEquals(null, object.optJSONArray(null));
assertEquals(null, object.optJSONObject(null));
assertEquals("", object.optString(null));
assertEquals(true, object.optBoolean(null, true));
assertEquals(0.0d, object.optDouble(null, 0.0d));
assertEquals(1, object.optInt(null, 1));
assertEquals(1L, object.optLong(null, 1L));
assertEquals("baz", object.optString(null, "baz"));
}
public void testToStringWithIndentFactor() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", new JSONArray(Arrays.asList(5, 6)));
object.put("bar", new JSONObject());
String foobar = "{\n" +
" \"foo\": [\n" +
" 5,\n" +
" 6\n" +
" ],\n" +
" \"bar\": {}\n" +
"}";
String barfoo = "{\n" +
" \"bar\": {},\n" +
" \"foo\": [\n" +
" 5,\n" +
" 6\n" +
" ]\n" +
"}";
String string = object.toString(5);
assertTrue(string, foobar.equals(string) || barfoo.equals(string));
}
public void testNames() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", 5);
object.put("bar", 6);
object.put("baz", 7);
JSONArray array = object.names();
assertTrue(array.toString().contains("foo"));
assertTrue(array.toString().contains("bar"));
assertTrue(array.toString().contains("baz"));
}
public void testKeysEmptyObject() {
JSONObject object = new JSONObject();
assertFalse(object.keys().hasNext());
try {
object.keys().next();
fail();
} catch (NoSuchElementException e) {
}
}
public void testKeys() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", 5);
object.put("bar", 6);
object.put("foo", 7);
@SuppressWarnings("unchecked")
Iterator keys = (Iterator) object.keys();
Set result = new HashSet();
assertTrue(keys.hasNext());
result.add(keys.next());
assertTrue(keys.hasNext());
result.add(keys.next());
assertFalse(keys.hasNext());
assertEquals(new HashSet(Arrays.asList("foo", "bar")), result);
try {
keys.next();
fail();
} catch (NoSuchElementException e) {
}
}
public void testMutatingKeysMutatesObject() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", 5);
Iterator keys = object.keys();
keys.next();
keys.remove();
assertEquals(0, object.length());
}
public void testQuote() {
// covered by JSONStringerTest.testEscaping
}
public void testQuoteNull() throws JSONException {
assertEquals("\"\"", JSONObject.quote(null));
}
public void testNumberToString() throws JSONException {
assertEquals("5", JSONObject.numberToString(5));
assertEquals("-0", JSONObject.numberToString(-0.0d));
assertEquals("9223372036854775806", JSONObject.numberToString(9223372036854775806L));
assertEquals("4.9E-324", JSONObject.numberToString(Double.MIN_VALUE));
assertEquals("1.7976931348623157E308", JSONObject.numberToString(Double.MAX_VALUE));
try {
JSONObject.numberToString(Double.NaN);
fail();
} catch (JSONException e) {
}
try {
JSONObject.numberToString(Double.NEGATIVE_INFINITY);
fail();
} catch (JSONException e) {
}
try {
JSONObject.numberToString(Double.POSITIVE_INFINITY);
fail();
} catch (JSONException e) {
}
assertEquals("0.001", JSONObject.numberToString(new BigDecimal("0.001")));
assertEquals("9223372036854775806",
JSONObject.numberToString(new BigInteger("9223372036854775806")));
try {
JSONObject.numberToString(null);
fail();
} catch (JSONException e) {
}
}
}
libandroid-json-org-java-20121204-20090211/src/test/java/org/json/JSONStringerTest.java 0000664 0000000 0000000 00000027006 12071360135 0027651 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.json;
import junit.framework.TestCase;
/**
* This black box test was written without inspecting the non-free org.json sourcecode.
*/
public class JSONStringerTest extends TestCase {
public void testEmptyStringer() {
// why isn't this the empty string?
assertNull(new JSONStringer().toString());
}
public void testValueJSONNull() throws JSONException {
JSONStringer stringer = new JSONStringer();
stringer.array();
stringer.value(JSONObject.NULL);
stringer.endArray();
assertEquals("[null]", stringer.toString());
}
public void testEmptyObject() throws JSONException {
JSONStringer stringer = new JSONStringer();
stringer.object();
stringer.endObject();
assertEquals("{}", stringer.toString());
}
public void testEmptyArray() throws JSONException {
JSONStringer stringer = new JSONStringer();
stringer.array();
stringer.endArray();
assertEquals("[]", stringer.toString());
}
public void testArray() throws JSONException {
JSONStringer stringer = new JSONStringer();
stringer.array();
stringer.value(false);
stringer.value(5.0);
stringer.value(5L);
stringer.value("five");
stringer.value(null);
stringer.endArray();
assertEquals("[false,5,5,\"five\",null]", stringer.toString());
}
public void testValueObjectMethods() throws JSONException {
JSONStringer stringer = new JSONStringer();
stringer.array();
stringer.value(Boolean.FALSE);
stringer.value(Double.valueOf(5.0));
stringer.value(Long.valueOf(5L));
stringer.endArray();
assertEquals("[false,5,5]", stringer.toString());
}
public void testKeyValue() throws JSONException {
JSONStringer stringer = new JSONStringer();
stringer.object();
stringer.key("a").value(false);
stringer.key("b").value(5.0);
stringer.key("c").value(5L);
stringer.key("d").value("five");
stringer.key("e").value(null);
stringer.endObject();
assertEquals("{\"a\":false," +
"\"b\":5," +
"\"c\":5," +
"\"d\":\"five\"," +
"\"e\":null}", stringer.toString());
}
/**
* Test what happens when extreme values are emitted. Such values are likely
* to be rounded during parsing.
*/
public void testNumericRepresentations() throws JSONException {
JSONStringer stringer = new JSONStringer();
stringer.array();
stringer.value(Long.MAX_VALUE);
stringer.value(Double.MIN_VALUE);
stringer.endArray();
assertEquals("[9223372036854775807,4.9E-324]", stringer.toString());
}
public void testWeirdNumbers() throws JSONException {
try {
new JSONStringer().array().value(Double.NaN);
fail();
} catch (JSONException e) {
}
try {
new JSONStringer().array().value(Double.NEGATIVE_INFINITY);
fail();
} catch (JSONException e) {
}
try {
new JSONStringer().array().value(Double.POSITIVE_INFINITY);
fail();
} catch (JSONException e) {
}
JSONStringer stringer = new JSONStringer();
stringer.array();
stringer.value(-0.0d);
stringer.value(0.0d);
stringer.endArray();
assertEquals("[-0,0]", stringer.toString());
}
public void testMismatchedScopes() {
try {
new JSONStringer().key("a");
fail();
} catch (JSONException e) {
}
try {
new JSONStringer().value("a");
fail();
} catch (JSONException e) {
}
try {
new JSONStringer().endObject();
fail();
} catch (JSONException e) {
}
try {
new JSONStringer().endArray();
fail();
} catch (JSONException e) {
}
try {
new JSONStringer().array().endObject();
fail();
} catch (JSONException e) {
}
try {
new JSONStringer().object().endArray();
fail();
} catch (JSONException e) {
}
try {
new JSONStringer().object().key("a").key("a");
fail();
} catch (JSONException e) {
}
try {
new JSONStringer().object().value(false);
fail();
} catch (JSONException e) {
}
}
public void testNullKey() {
try {
new JSONStringer().object().key(null);
fail();
} catch (JSONException e) {
}
}
public void testRepeatedKey() throws JSONException {
JSONStringer stringer = new JSONStringer();
stringer.object();
stringer.key("a").value(true);
stringer.key("a").value(false);
stringer.endObject();
// JSONStringer doesn't attempt to detect duplicates
assertEquals("{\"a\":true,\"a\":false}", stringer.toString());
}
public void testEmptyKey() throws JSONException {
JSONStringer stringer = new JSONStringer();
stringer.object();
stringer.key("").value(false);
stringer.endObject();
assertEquals("{\"\":false}", stringer.toString()); // legit behaviour!
}
public void testEscaping() throws JSONException {
assertEscapedAllWays("a", "a");
assertEscapedAllWays("a\\\"", "a\"");
assertEscapedAllWays("\\\"", "\"");
assertEscapedAllWays(":", ":");
assertEscapedAllWays(",", ",");
assertEscapedAllWays("\\b", "\b");
assertEscapedAllWays("\\f", "\f");
assertEscapedAllWays("\\n", "\n");
assertEscapedAllWays("\\r", "\r");
assertEscapedAllWays("\\t", "\t");
assertEscapedAllWays(" ", " ");
assertEscapedAllWays("\\\\", "\\");
assertEscapedAllWays("{", "{");
assertEscapedAllWays("}", "}");
assertEscapedAllWays("[", "[");
assertEscapedAllWays("]", "]");
assertEscapedAllWays("\\u0000", "\0");
assertEscapedAllWays("\\u0019", "\u0019");
assertEscapedAllWays(" ", "\u0020");
}
private void assertEscapedAllWays(String escaped, String original) throws JSONException {
assertEquals("{\"" + escaped + "\":false}",
new JSONStringer().object().key(original).value(false).endObject().toString());
assertEquals("{\"a\":\"" + escaped + "\"}",
new JSONStringer().object().key("a").value(original).endObject().toString());
assertEquals("[\"" + escaped + "\"]",
new JSONStringer().array().value(original).endArray().toString());
assertEquals("\"" + escaped + "\"", JSONObject.quote(original));
}
public void testJSONArrayAsValue() throws JSONException {
JSONArray array = new JSONArray();
array.put(false);
JSONStringer stringer = new JSONStringer();
stringer.array();
stringer.value(array);
stringer.endArray();
assertEquals("[[false]]", stringer.toString());
}
public void testJSONObjectAsValue() throws JSONException {
JSONObject object = new JSONObject();
object.put("a", false);
JSONStringer stringer = new JSONStringer();
stringer.object();
stringer.key("b").value(object);
stringer.endObject();
assertEquals("{\"b\":{\"a\":false}}", stringer.toString());
}
public void testArrayNestingMaxDepthSupports20() throws JSONException {
JSONStringer stringer = new JSONStringer();
for (int i = 0; i < 20; i++) {
stringer.array();
}
for (int i = 0; i < 20; i++) {
stringer.endArray();
}
assertEquals("[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]", stringer.toString());
stringer = new JSONStringer();
for (int i = 0; i < 20; i++) {
stringer.array();
}
}
public void testObjectNestingMaxDepthSupports20() throws JSONException {
JSONStringer stringer = new JSONStringer();
for (int i = 0; i < 20; i++) {
stringer.object();
stringer.key("a");
}
stringer.value(false);
for (int i = 0; i < 20; i++) {
stringer.endObject();
}
assertEquals("{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":" +
"{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":{\"a\":false" +
"}}}}}}}}}}}}}}}}}}}}", stringer.toString());
stringer = new JSONStringer();
for (int i = 0; i < 20; i++) {
stringer.object();
stringer.key("a");
}
}
public void testMixedMaxDepthSupports20() throws JSONException {
JSONStringer stringer = new JSONStringer();
for (int i = 0; i < 20; i+=2) {
stringer.array();
stringer.object();
stringer.key("a");
}
stringer.value(false);
for (int i = 0; i < 20; i+=2) {
stringer.endObject();
stringer.endArray();
}
assertEquals("[{\"a\":[{\"a\":[{\"a\":[{\"a\":[{\"a\":" +
"[{\"a\":[{\"a\":[{\"a\":[{\"a\":[{\"a\":false" +
"}]}]}]}]}]}]}]}]}]}]", stringer.toString());
stringer = new JSONStringer();
for (int i = 0; i < 20; i+=2) {
stringer.array();
stringer.object();
stringer.key("a");
}
}
public void testMaxDepthWithArrayValue() throws JSONException {
JSONArray array = new JSONArray();
array.put(false);
JSONStringer stringer = new JSONStringer();
for (int i = 0; i < 20; i++) {
stringer.array();
}
stringer.value(array);
for (int i = 0; i < 20; i++) {
stringer.endArray();
}
assertEquals("[[[[[[[[[[[[[[[[[[[[[false]]]]]]]]]]]]]]]]]]]]]", stringer.toString());
}
public void testMaxDepthWithObjectValue() throws JSONException {
JSONObject object = new JSONObject();
object.put("a", false);
JSONStringer stringer = new JSONStringer();
for (int i = 0; i < 20; i++) {
stringer.object();
stringer.key("b");
}
stringer.value(object);
for (int i = 0; i < 20; i++) {
stringer.endObject();
}
assertEquals("{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":" +
"{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":{\"b\":" +
"{\"a\":false}}}}}}}}}}}}}}}}}}}}}", stringer.toString());
}
public void testMultipleRoots() throws JSONException {
JSONStringer stringer = new JSONStringer();
stringer.array();
stringer.endArray();
try {
stringer.object();
fail();
} catch (JSONException e) {
}
}
}
libandroid-json-org-java-20121204-20090211/src/test/java/org/json/JSONTokenerTest.java 0000664 0000000 0000000 00000055266 12071360135 0027474 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.json;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
/**
* This black box test was written without inspecting the non-free org.json sourcecode.
*/
public class JSONTokenerTest extends TestCase {
public void testNulls() throws JSONException {
// JSONTokener accepts null, only to fail later on almost all APIs!
new JSONTokener(null).back();
try {
new JSONTokener(null).more();
fail();
} catch (NullPointerException e) {
}
try {
new JSONTokener(null).next();
fail();
} catch (NullPointerException e) {
}
try {
new JSONTokener(null).next(3);
fail();
} catch (NullPointerException e) {
}
try {
new JSONTokener(null).next('A');
fail();
} catch (NullPointerException e) {
}
try {
new JSONTokener(null).nextClean();
fail();
} catch (NullPointerException e) {
}
try {
new JSONTokener(null).nextString('"');
fail();
} catch (NullPointerException e) {
}
try {
new JSONTokener(null).nextTo('A');
fail();
} catch (NullPointerException e) {
}
try {
new JSONTokener(null).nextTo("ABC");
fail();
} catch (NullPointerException e) {
}
try {
new JSONTokener(null).nextValue();
fail();
} catch (NullPointerException e) {
}
try {
new JSONTokener(null).skipPast("ABC");
fail();
} catch (NullPointerException e) {
}
try {
new JSONTokener(null).skipTo('A');
fail();
} catch (NullPointerException e) {
}
assertEquals("foo! at character 0 of null",
new JSONTokener(null).syntaxError("foo!").getMessage());
assertEquals(" at character 0 of null", new JSONTokener(null).toString());
}
public void testEmptyString() throws JSONException {
JSONTokener backTokener = new JSONTokener("");
backTokener.back();
assertEquals(" at character 0 of ", backTokener.toString());
assertFalse(new JSONTokener("").more());
assertEquals('\0', new JSONTokener("").next());
try {
new JSONTokener("").next(3);
fail();
} catch (JSONException expected) {
}
try {
new JSONTokener("").next('A');
fail();
} catch (JSONException e) {
}
assertEquals('\0', new JSONTokener("").nextClean());
try {
new JSONTokener("").nextString('"');
fail();
} catch (JSONException e) {
}
assertEquals("", new JSONTokener("").nextTo('A'));
assertEquals("", new JSONTokener("").nextTo("ABC"));
try {
new JSONTokener("").nextValue();
fail();
} catch (JSONException e) {
}
new JSONTokener("").skipPast("ABC");
assertEquals('\0', new JSONTokener("").skipTo('A'));
assertEquals("foo! at character 0 of ",
new JSONTokener("").syntaxError("foo!").getMessage());
assertEquals(" at character 0 of ", new JSONTokener("").toString());
}
public void testCharacterNavigation() throws JSONException {
JSONTokener abcdeTokener = new JSONTokener("ABCDE");
assertEquals('A', abcdeTokener.next());
assertEquals('B', abcdeTokener.next('B'));
assertEquals("CD", abcdeTokener.next(2));
try {
abcdeTokener.next(2);
fail();
} catch (JSONException e) {
}
assertEquals('E', abcdeTokener.nextClean());
assertEquals('\0', abcdeTokener.next());
assertFalse(abcdeTokener.more());
abcdeTokener.back();
assertTrue(abcdeTokener.more());
assertEquals('E', abcdeTokener.next());
}
public void testBackNextAndMore() throws JSONException {
JSONTokener abcTokener = new JSONTokener("ABC");
assertTrue(abcTokener.more());
abcTokener.next();
abcTokener.next();
assertTrue(abcTokener.more());
abcTokener.next();
assertFalse(abcTokener.more());
abcTokener.back();
assertTrue(abcTokener.more());
abcTokener.next();
assertFalse(abcTokener.more());
abcTokener.back();
abcTokener.back();
abcTokener.back();
abcTokener.back(); // you can back up before the beginning of a String!
assertEquals('A', abcTokener.next());
}
public void testNextMatching() throws JSONException {
JSONTokener abcdTokener = new JSONTokener("ABCD");
assertEquals('A', abcdTokener.next('A'));
try {
abcdTokener.next('C'); // although it failed, this op consumes a character of input
fail();
} catch (JSONException e) {
}
assertEquals('C', abcdTokener.next('C'));
assertEquals('D', abcdTokener.next('D'));
try {
abcdTokener.next('E');
fail();
} catch (JSONException e) {
}
}
public void testNextN() throws JSONException {
JSONTokener abcdeTokener = new JSONTokener("ABCDEF");
assertEquals("", abcdeTokener.next(0));
try {
abcdeTokener.next(7);
fail();
} catch (JSONException e) {
}
assertEquals("ABC", abcdeTokener.next(3));
try {
abcdeTokener.next(4);
fail();
} catch (JSONException e) {
}
}
public void testNextNWithAllRemaining() throws JSONException {
JSONTokener tokener = new JSONTokener("ABCDEF");
tokener.next(3);
try {
tokener.next(3);
} catch (JSONException e) {
AssertionFailedError error = new AssertionFailedError("off-by-one error?");
error.initCause(e);
throw error;
}
}
public void testNext0() throws JSONException {
JSONTokener tokener = new JSONTokener("ABCDEF");
tokener.next(5);
tokener.next();
try {
tokener.next(0);
} catch (JSONException e) {
Error error = new AssertionFailedError("Returning an empty string should be valid");
error.initCause(e);
throw error;
}
}
public void testNextCleanComments() throws JSONException {
JSONTokener tokener = new JSONTokener(
" A /*XX*/B/*XX//XX\n//XX\nXX*/C//X//X//X\nD/*X*///X\n");
assertEquals('A', tokener.nextClean());
assertEquals('B', tokener.nextClean());
assertEquals('C', tokener.nextClean());
assertEquals('D', tokener.nextClean());
assertEquals('\0', tokener.nextClean());
}
public void testNextCleanNestedCStyleComments() throws JSONException {
JSONTokener tokener = new JSONTokener("A /* B /* C */ D */ E");
assertEquals('A', tokener.nextClean());
assertEquals('D', tokener.nextClean());
assertEquals('*', tokener.nextClean());
assertEquals('/', tokener.nextClean());
assertEquals('E', tokener.nextClean());
}
/**
* Some applications rely on parsing '#' to lead an end-of-line comment.
* http://b/2571423
*/
public void testNextCleanHashComments() throws JSONException {
JSONTokener tokener = new JSONTokener("A # B */ /* C */ \nD #");
assertEquals('A', tokener.nextClean());
assertEquals('D', tokener.nextClean());
assertEquals('\0', tokener.nextClean());
}
public void testNextCleanCommentsTrailingSingleSlash() throws JSONException {
JSONTokener tokener = new JSONTokener(" / S /");
assertEquals('/', tokener.nextClean());
assertEquals('S', tokener.nextClean());
assertEquals('/', tokener.nextClean());
assertEquals("nextClean doesn't consume a trailing slash",
'\0', tokener.nextClean());
}
public void testNextCleanTrailingOpenComment() throws JSONException {
try {
new JSONTokener(" /* ").nextClean();
fail();
} catch (JSONException e) {
}
assertEquals('\0', new JSONTokener(" // ").nextClean());
}
public void testNextCleanNewlineDelimiters() throws JSONException {
assertEquals('B', new JSONTokener(" // \r\n B ").nextClean());
assertEquals('B', new JSONTokener(" // \n B ").nextClean());
assertEquals('B', new JSONTokener(" // \r B ").nextClean());
}
public void testNextCleanSkippedWhitespace() throws JSONException {
assertEquals("character tabulation", 'A', new JSONTokener("\tA").nextClean());
assertEquals("line feed", 'A', new JSONTokener("\nA").nextClean());
assertEquals("carriage return", 'A', new JSONTokener("\rA").nextClean());
assertEquals("space", 'A', new JSONTokener(" A").nextClean());
}
/**
* Tests which characters tokener treats as ignorable whitespace. See Kevin Bourrillion's
* list
* of whitespace characters .
*/
public void testNextCleanRetainedWhitespace() throws JSONException {
assertNotClean("null", '\u0000');
assertNotClean("next line", '\u0085');
assertNotClean("non-breaking space", '\u00a0');
assertNotClean("ogham space mark", '\u1680');
assertNotClean("mongolian vowel separator", '\u180e');
assertNotClean("en quad", '\u2000');
assertNotClean("em quad", '\u2001');
assertNotClean("en space", '\u2002');
assertNotClean("em space", '\u2003');
assertNotClean("three-per-em space", '\u2004');
assertNotClean("four-per-em space", '\u2005');
assertNotClean("six-per-em space", '\u2006');
assertNotClean("figure space", '\u2007');
assertNotClean("punctuation space", '\u2008');
assertNotClean("thin space", '\u2009');
assertNotClean("hair space", '\u200a');
assertNotClean("zero-width space", '\u200b');
assertNotClean("left-to-right mark", '\u200e');
assertNotClean("right-to-left mark", '\u200f');
assertNotClean("line separator", '\u2028');
assertNotClean("paragraph separator", '\u2029');
assertNotClean("narrow non-breaking space", '\u202f');
assertNotClean("medium mathematical space", '\u205f');
assertNotClean("ideographic space", '\u3000');
assertNotClean("line tabulation", '\u000b');
assertNotClean("form feed", '\u000c');
assertNotClean("information separator 4", '\u001c');
assertNotClean("information separator 3", '\u001d');
assertNotClean("information separator 2", '\u001e');
assertNotClean("information separator 1", '\u001f');
}
private void assertNotClean(String name, char c) throws JSONException {
assertEquals("The character " + name + " is not whitespace according to the JSON spec.",
c, new JSONTokener(new String(new char[] { c, 'A' })).nextClean());
}
public void testNextString() throws JSONException {
assertEquals("", new JSONTokener("'").nextString('\''));
assertEquals("", new JSONTokener("\"").nextString('\"'));
assertEquals("ABC", new JSONTokener("ABC'DEF").nextString('\''));
assertEquals("ABC", new JSONTokener("ABC'''DEF").nextString('\''));
// nextString permits slash-escaping of arbitrary characters!
assertEquals("ABC", new JSONTokener("A\\B\\C'DEF").nextString('\''));
JSONTokener tokener = new JSONTokener(" 'abc' 'def' \"ghi\"");
tokener.next();
assertEquals('\'', tokener.next());
assertEquals("abc", tokener.nextString('\''));
tokener.next();
assertEquals('\'', tokener.next());
assertEquals("def", tokener.nextString('\''));
tokener.next();
assertEquals('"', tokener.next());
assertEquals("ghi", tokener.nextString('\"'));
assertFalse(tokener.more());
}
public void testNextStringNoDelimiter() throws JSONException {
try {
new JSONTokener("").nextString('\'');
fail();
} catch (JSONException e) {
}
JSONTokener tokener = new JSONTokener(" 'abc");
tokener.next();
tokener.next();
try {
tokener.next('\'');
fail();
} catch (JSONException e) {
}
}
public void testNextStringEscapedQuote() throws JSONException {
try {
new JSONTokener("abc\\").nextString('"');
fail();
} catch (JSONException e) {
}
// we're mixing Java escaping like \" and JavaScript escaping like \\\"
// which makes these tests extra tricky to read!
assertEquals("abc\"def", new JSONTokener("abc\\\"def\"ghi").nextString('"'));
assertEquals("abc\\def", new JSONTokener("abc\\\\def\"ghi").nextString('"'));
assertEquals("abc/def", new JSONTokener("abc\\/def\"ghi").nextString('"'));
assertEquals("abc\bdef", new JSONTokener("abc\\bdef\"ghi").nextString('"'));
assertEquals("abc\fdef", new JSONTokener("abc\\fdef\"ghi").nextString('"'));
assertEquals("abc\ndef", new JSONTokener("abc\\ndef\"ghi").nextString('"'));
assertEquals("abc\rdef", new JSONTokener("abc\\rdef\"ghi").nextString('"'));
assertEquals("abc\tdef", new JSONTokener("abc\\tdef\"ghi").nextString('"'));
}
public void testNextStringUnicodeEscaped() throws JSONException {
// we're mixing Java escaping like \\ and JavaScript escaping like \\u
assertEquals("abc def", new JSONTokener("abc\\u0020def\"ghi").nextString('"'));
assertEquals("abcU0020def", new JSONTokener("abc\\U0020def\"ghi").nextString('"'));
// JSON requires 4 hex characters after a unicode escape
try {
new JSONTokener("abc\\u002\"").nextString('"');
fail();
} catch (NumberFormatException e) {
} catch (JSONException e) {
}
try {
new JSONTokener("abc\\u").nextString('"');
fail();
} catch (JSONException e) {
}
try {
new JSONTokener("abc\\u \"").nextString('"');
fail();
} catch (NumberFormatException e) {
}
assertEquals("abc\"def", new JSONTokener("abc\\u0022def\"ghi").nextString('"'));
try {
new JSONTokener("abc\\u000G\"").nextString('"');
fail();
} catch (NumberFormatException e) {
}
}
public void testNextStringNonQuote() throws JSONException {
assertEquals("AB", new JSONTokener("ABC").nextString('C'));
assertEquals("ABCD", new JSONTokener("AB\\CDC").nextString('C'));
assertEquals("AB\nC", new JSONTokener("AB\\nCn").nextString('n'));
}
public void testNextTo() throws JSONException {
assertEquals("ABC", new JSONTokener("ABCDEFG").nextTo("DHI"));
assertEquals("ABCDEF", new JSONTokener("ABCDEF").nextTo(""));
JSONTokener tokener = new JSONTokener("ABC\rDEF\nGHI\r\nJKL");
assertEquals("ABC", tokener.nextTo("M"));
assertEquals('\r', tokener.next());
assertEquals("DEF", tokener.nextTo("M"));
assertEquals('\n', tokener.next());
assertEquals("GHI", tokener.nextTo("M"));
assertEquals('\r', tokener.next());
assertEquals('\n', tokener.next());
assertEquals("JKL", tokener.nextTo("M"));
tokener = new JSONTokener("ABCDEFGHI");
assertEquals("ABC", tokener.nextTo("DEF"));
assertEquals("", tokener.nextTo("DEF"));
assertEquals('D', tokener.next());
assertEquals("", tokener.nextTo("DEF"));
assertEquals('E', tokener.next());
assertEquals("", tokener.nextTo("DEF"));
assertEquals('F', tokener.next());
assertEquals("GHI", tokener.nextTo("DEF"));
assertEquals("", tokener.nextTo("DEF"));
tokener = new JSONTokener(" \t \fABC \t DEF");
assertEquals("ABC", tokener.nextTo("DEF"));
assertEquals('D', tokener.next());
tokener = new JSONTokener(" \t \fABC \n DEF");
assertEquals("ABC", tokener.nextTo("\n"));
assertEquals("", tokener.nextTo("\n"));
tokener = new JSONTokener("");
try {
tokener.nextTo(null);
fail();
} catch (NullPointerException e) {
}
}
public void testNextToTrimming() {
assertEquals("ABC", new JSONTokener("\t ABC \tDEF").nextTo("DE"));
assertEquals("ABC", new JSONTokener("\t ABC \tDEF").nextTo('D'));
}
public void testNextToTrailing() {
assertEquals("ABC DEF", new JSONTokener("\t ABC DEF \t").nextTo("G"));
assertEquals("ABC DEF", new JSONTokener("\t ABC DEF \t").nextTo('G'));
}
public void testNextToDoesntStopOnNull() {
String message = "nextTo() shouldn't stop after \\0 characters";
JSONTokener tokener = new JSONTokener(" \0\t \fABC \n DEF");
assertEquals(message, "ABC", tokener.nextTo("D"));
assertEquals(message, '\n', tokener.next());
assertEquals(message, "", tokener.nextTo("D"));
}
public void testNextToConsumesNull() {
String message = "nextTo shouldn't consume \\0.";
JSONTokener tokener = new JSONTokener("ABC\0DEF");
assertEquals(message, "ABC", tokener.nextTo("\0"));
assertEquals(message, '\0', tokener.next());
assertEquals(message, "DEF", tokener.nextTo("\0"));
}
public void testSkipPast() {
JSONTokener tokener = new JSONTokener("ABCDEF");
tokener.skipPast("ABC");
assertEquals('D', tokener.next());
tokener.skipPast("EF");
assertEquals('\0', tokener.next());
tokener = new JSONTokener("ABCDEF");
tokener.skipPast("ABCDEF");
assertEquals('\0', tokener.next());
tokener = new JSONTokener("ABCDEF");
tokener.skipPast("G");
assertEquals('\0', tokener.next());
tokener = new JSONTokener("ABC\0ABC");
tokener.skipPast("ABC");
assertEquals('\0', tokener.next());
assertEquals('A', tokener.next());
tokener = new JSONTokener("\0ABC");
tokener.skipPast("ABC");
assertEquals('\0', tokener.next());
tokener = new JSONTokener("ABC\nDEF");
tokener.skipPast("DEF");
assertEquals('\0', tokener.next());
tokener = new JSONTokener("ABC");
tokener.skipPast("ABCDEF");
assertEquals('\0', tokener.next());
tokener = new JSONTokener("ABCDABCDABCD");
tokener.skipPast("ABC");
assertEquals('D', tokener.next());
tokener.skipPast("ABC");
assertEquals('D', tokener.next());
tokener.skipPast("ABC");
assertEquals('D', tokener.next());
tokener = new JSONTokener("");
try {
tokener.skipPast(null);
fail();
} catch (NullPointerException e) {
}
}
public void testSkipTo() {
JSONTokener tokener = new JSONTokener("ABCDEF");
tokener.skipTo('A');
assertEquals('A', tokener.next());
tokener.skipTo('D');
assertEquals('D', tokener.next());
tokener.skipTo('G');
assertEquals('E', tokener.next());
tokener.skipTo('A');
assertEquals('F', tokener.next());
tokener = new JSONTokener("ABC\nDEF");
tokener.skipTo('F');
assertEquals('F', tokener.next());
tokener = new JSONTokener("ABCfDEF");
tokener.skipTo('F');
assertEquals('F', tokener.next());
tokener = new JSONTokener("ABC/* DEF */");
tokener.skipTo('D');
assertEquals('D', tokener.next());
}
public void testSkipToStopsOnNull() {
JSONTokener tokener = new JSONTokener("ABC\0DEF");
tokener.skipTo('F');
assertEquals("skipTo shouldn't stop when it sees '\\0'", 'F', tokener.next());
}
public void testBomIgnoredAsFirstCharacterOfDocument() throws JSONException {
JSONTokener tokener = new JSONTokener("\ufeff[]");
JSONArray array = (JSONArray) tokener.nextValue();
assertEquals(0, array.length());
}
public void testBomTreatedAsCharacterInRestOfDocument() throws JSONException {
JSONTokener tokener = new JSONTokener("[\ufeff]");
JSONArray array = (JSONArray) tokener.nextValue();
assertEquals(1, array.length());
}
public void testDehexchar() {
assertEquals( 0, JSONTokener.dehexchar('0'));
assertEquals( 1, JSONTokener.dehexchar('1'));
assertEquals( 2, JSONTokener.dehexchar('2'));
assertEquals( 3, JSONTokener.dehexchar('3'));
assertEquals( 4, JSONTokener.dehexchar('4'));
assertEquals( 5, JSONTokener.dehexchar('5'));
assertEquals( 6, JSONTokener.dehexchar('6'));
assertEquals( 7, JSONTokener.dehexchar('7'));
assertEquals( 8, JSONTokener.dehexchar('8'));
assertEquals( 9, JSONTokener.dehexchar('9'));
assertEquals(10, JSONTokener.dehexchar('A'));
assertEquals(11, JSONTokener.dehexchar('B'));
assertEquals(12, JSONTokener.dehexchar('C'));
assertEquals(13, JSONTokener.dehexchar('D'));
assertEquals(14, JSONTokener.dehexchar('E'));
assertEquals(15, JSONTokener.dehexchar('F'));
assertEquals(10, JSONTokener.dehexchar('a'));
assertEquals(11, JSONTokener.dehexchar('b'));
assertEquals(12, JSONTokener.dehexchar('c'));
assertEquals(13, JSONTokener.dehexchar('d'));
assertEquals(14, JSONTokener.dehexchar('e'));
assertEquals(15, JSONTokener.dehexchar('f'));
for (int c = 0; c <= 0xFFFF; c++) {
if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) {
continue;
}
assertEquals("dehexchar " + c, -1, JSONTokener.dehexchar((char) c));
}
}
}
libandroid-json-org-java-20121204-20090211/src/test/java/org/json/ParsingTest.java 0000664 0000000 0000000 00000024244 12071360135 0026766 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.json;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import junit.framework.TestCase;
public class ParsingTest extends TestCase {
public void testParsingNoObjects() {
try {
new JSONTokener("").nextValue();
fail();
} catch (JSONException e) {
}
}
public void testParsingLiterals() throws JSONException {
assertParsed(Boolean.TRUE, "true");
assertParsed(Boolean.FALSE, "false");
assertParsed(JSONObject.NULL, "null");
assertParsed(JSONObject.NULL, "NULL");
assertParsed(Boolean.FALSE, "False");
assertParsed(Boolean.TRUE, "truE");
}
public void testParsingQuotedStrings() throws JSONException {
assertParsed("abc", "\"abc\"");
assertParsed("123", "\"123\"");
assertParsed("foo\nbar", "\"foo\\nbar\"");
assertParsed("foo bar", "\"foo\\u0020bar\"");
assertParsed("\"{}[]/\\:,=;#", "\"\\\"{}[]/\\\\:,=;#\"");
}
public void testParsingSingleQuotedStrings() throws JSONException {
assertParsed("abc", "'abc'");
assertParsed("123", "'123'");
assertParsed("foo\nbar", "'foo\\nbar'");
assertParsed("foo bar", "'foo\\u0020bar'");
assertParsed("\"{}[]/\\:,=;#", "'\\\"{}[]/\\\\:,=;#'");
}
public void testParsingUnquotedStrings() throws JSONException {
assertParsed("abc", "abc");
assertParsed("123abc", "123abc");
assertParsed("123e0x", "123e0x");
assertParsed("123e", "123e");
assertParsed("123ee21", "123ee21");
assertParsed("0xFFFFFFFFFFFFFFFFF", "0xFFFFFFFFFFFFFFFFF");
}
/**
* Unfortunately the original implementation attempts to figure out what
* Java number type best suits an input value.
*/
public void testParsingNumbersThatAreBestRepresentedAsLongs() throws JSONException {
assertParsed(9223372036854775807L, "9223372036854775807");
assertParsed(9223372036854775806L, "9223372036854775806");
assertParsed(-9223372036854775808L, "-9223372036854775808");
assertParsed(-9223372036854775807L, "-9223372036854775807");
}
public void testParsingNumbersThatAreBestRepresentedAsIntegers() throws JSONException {
assertParsed(0, "0");
assertParsed(5, "5");
assertParsed(-2147483648, "-2147483648");
assertParsed(2147483647, "2147483647");
}
public void testParsingNegativeZero() throws JSONException {
assertParsed(0, "-0");
}
public void testParsingIntegersWithAdditionalPrecisionYieldDoubles() throws JSONException {
assertParsed(1d, "1.00");
assertParsed(1d, "1.0");
assertParsed(0d, "0.0");
assertParsed(-0d, "-0.0");
}
public void testParsingNumbersThatAreBestRepresentedAsDoubles() throws JSONException {
assertParsed(9.223372036854776E18, "9223372036854775808");
assertParsed(-9.223372036854776E18, "-9223372036854775809");
assertParsed(1.7976931348623157E308, "1.7976931348623157e308");
assertParsed(2.2250738585072014E-308, "2.2250738585072014E-308");
assertParsed(4.9E-324, "4.9E-324");
assertParsed(4.9E-324, "4.9e-324");
}
public void testParsingOctalNumbers() throws JSONException {
assertParsed(5, "05");
assertParsed(8, "010");
assertParsed(1046, "02026");
}
public void testParsingHexNumbers() throws JSONException {
assertParsed(5, "0x5");
assertParsed(16, "0x10");
assertParsed(8230, "0x2026");
assertParsed(180150010, "0xABCDEFA");
assertParsed(2077093803, "0x7BCDEFAB");
}
public void testParsingLargeHexValues() throws JSONException {
assertParsed(Integer.MAX_VALUE, "0x7FFFFFFF");
String message = "Hex values are parsed as Strings if their signed " +
"value is greater than Integer.MAX_VALUE.";
assertParsed(message, 0x80000000L, "0x80000000");
}
public void test64BitHexValues() throws JSONException {
assertParsed("Large hex longs shouldn't be yield ints or strings",
-1L, "0xFFFFFFFFFFFFFFFF");
}
public void testParsingWithCommentsAndWhitespace() throws JSONException {
assertParsed("baz", " // foo bar \n baz");
assertParsed("baz", " // foo bar \r baz");
assertParsed("baz", " // foo bar \r\n baz");
assertParsed("baz", " # foo bar \n baz");
assertParsed("baz", " # foo bar \r baz");
assertParsed("baz", " # foo bar \r\n baz");
assertParsed(5, " /* foo bar \n baz */ 5");
assertParsed(5, " /* foo bar \n baz */ 5 // quux");
assertParsed(5, " 5 ");
assertParsed(5, " 5 \r\n\t ");
assertParsed(5, "\r\n\t 5 ");
}
public void testParsingArrays() throws JSONException {
assertParsed(array(), "[]");
assertParsed(array(5, 6, true), "[5,6,true]");
assertParsed(array(5, 6, array()), "[5,6,[]]");
assertParsed(array(5, 6, 7), "[5;6;7]");
assertParsed(array(5, 6, 7), "[5 , 6 \t; \r\n 7\n]");
assertParsed(array(5, 6, 7, null), "[5,6,7,]");
assertParsed(array(null, null), "[,]");
assertParsed(array(5, null, null, null, 5), "[5,,,,5]");
assertParsed(array(null, 5), "[,5]");
assertParsed(array(null, null, null), "[,,]");
assertParsed(array(null, null, null, 5), "[,,,5]");
}
public void testParsingObjects() throws JSONException {
assertParsed(object("foo", 5), "{\"foo\": 5}");
assertParsed(object("foo", 5), "{foo: 5}");
assertParsed(object("foo", 5, "bar", "baz"), "{\"foo\": 5, \"bar\": \"baz\"}");
assertParsed(object("foo", 5, "bar", "baz"), "{\"foo\": 5; \"bar\": \"baz\"}");
assertParsed(object("foo", 5, "bar", "baz"), "{\"foo\"= 5; \"bar\"= \"baz\"}");
assertParsed(object("foo", 5, "bar", "baz"), "{\"foo\"=> 5; \"bar\"=> \"baz\"}");
assertParsed(object("foo", object(), "bar", array()), "{\"foo\"=> {}; \"bar\"=> []}");
assertParsed(object("foo", object("foo", array(5, 6))), "{\"foo\": {\"foo\": [5, 6]}}");
assertParsed(object("foo", object("foo", array(5, 6))), "{\"foo\":\n\t{\t \"foo\":[5,\r6]}}");
}
public void testSyntaxProblemUnterminatedObject() {
assertParseFail("{");
assertParseFail("{\"foo\"");
assertParseFail("{\"foo\":");
assertParseFail("{\"foo\":bar");
assertParseFail("{\"foo\":bar,");
assertParseFail("{\"foo\":bar,\"baz\"");
assertParseFail("{\"foo\":bar,\"baz\":");
assertParseFail("{\"foo\":bar,\"baz\":true");
assertParseFail("{\"foo\":bar,\"baz\":true,");
}
public void testSyntaxProblemEmptyString() {
assertParseFail("");
}
public void testSyntaxProblemUnterminatedArray() {
assertParseFail("[");
assertParseFail("[,");
assertParseFail("[,,");
assertParseFail("[true");
assertParseFail("[true,");
assertParseFail("[true,,");
}
public void testSyntaxProblemMalformedObject() {
assertParseFail("{:}");
assertParseFail("{\"key\":}");
assertParseFail("{:true}");
assertParseFail("{\"key\":true:}");
assertParseFail("{null:true}");
assertParseFail("{true:true}");
assertParseFail("{0xFF:true}");
}
private void assertParseFail(String malformedJson) {
try {
new JSONTokener(malformedJson).nextValue();
fail("Successfully parsed: \"" + malformedJson + "\"");
} catch (JSONException e) {
} catch (StackOverflowError e) {
fail("Stack overflowed on input: \"" + malformedJson + "\"");
}
}
private JSONArray array(Object... elements) {
return new JSONArray(Arrays.asList(elements));
}
private JSONObject object(Object... keyValuePairs) throws JSONException {
JSONObject result = new JSONObject();
for (int i = 0; i < keyValuePairs.length; i+=2) {
result.put((String) keyValuePairs[i], keyValuePairs[i+1]);
}
return result;
}
private void assertParsed(String message, Object expected, String json) throws JSONException {
Object actual = new JSONTokener(json).nextValue();
actual = canonicalize(actual);
expected = canonicalize(expected);
assertEquals("For input \"" + json + "\" " + message, expected, actual);
}
private void assertParsed(Object expected, String json) throws JSONException {
assertParsed("", expected, json);
}
/**
* Since they don't implement equals or hashCode properly, this recursively
* replaces JSONObjects with an equivalent HashMap, and JSONArrays with the
* equivalent ArrayList.
*/
private Object canonicalize(Object input) throws JSONException {
if (input instanceof JSONArray) {
JSONArray array = (JSONArray) input;
List result = new ArrayList();
for (int i = 0; i < array.length(); i++) {
result.add(canonicalize(array.opt(i)));
}
return result;
} else if (input instanceof JSONObject) {
JSONObject object = (JSONObject) input;
Map result = new HashMap();
for (Iterator> i = object.keys(); i.hasNext(); ) {
String key = (String) i.next();
result.put(key, canonicalize(object.get(key)));
}
return result;
} else {
return input;
}
}
}
libandroid-json-org-java-20121204-20090211/src/test/java/org/json/SelfUseTest.java 0000664 0000000 0000000 00000017027 12071360135 0026732 0 ustar 00root root 0000000 0000000 /*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.json;
import junit.framework.TestCase;
/**
* These tests checks self use calls. For the most part we doesn't attempt to
* cover self-use, except in those cases where our clean room implementation
* does it.
*
* This black box test was written without inspecting the non-free org.json
* sourcecode.
*/
public class SelfUseTest extends TestCase {
private int objectPutCalls = 0;
private int objectGetCalls = 0;
private int objectOptCalls = 0;
private int objectOptTypeCalls = 0;
private int arrayPutCalls = 0;
private int arrayGetCalls = 0;
private int arrayOptCalls = 0;
private int arrayOptTypeCalls = 0;
private int tokenerNextCalls = 0;
private int tokenerNextValueCalls = 0;
private final JSONObject object = new JSONObject() {
@Override public JSONObject put(String name, Object value) throws JSONException {
objectPutCalls++;
return super.put(name, value);
}
@Override public Object get(String name) throws JSONException {
objectGetCalls++;
return super.get(name);
}
@Override public Object opt(String name) {
objectOptCalls++;
return super.opt(name);
}
@Override public boolean optBoolean(String key, boolean defaultValue) {
objectOptTypeCalls++;
return super.optBoolean(key, defaultValue);
}
@Override public double optDouble(String key, double defaultValue) {
objectOptTypeCalls++;
return super.optDouble(key, defaultValue);
}
@Override public int optInt(String key, int defaultValue) {
objectOptTypeCalls++;
return super.optInt(key, defaultValue);
}
@Override public long optLong(String key, long defaultValue) {
objectOptTypeCalls++;
return super.optLong(key, defaultValue);
}
@Override public String optString(String key, String defaultValue) {
objectOptTypeCalls++;
return super.optString(key, defaultValue);
}
};
private final JSONArray array = new JSONArray() {
@Override public JSONArray put(int index, Object value) throws JSONException {
arrayPutCalls++;
return super.put(index, value);
}
@Override public Object get(int index) throws JSONException {
arrayGetCalls++;
return super.get(index);
}
@Override public Object opt(int index) {
arrayOptCalls++;
return super.opt(index);
}
@Override public boolean optBoolean(int index, boolean fallback) {
arrayOptTypeCalls++;
return super.optBoolean(index, fallback);
}
@Override public double optDouble(int index, double fallback) {
arrayOptTypeCalls++;
return super.optDouble(index, fallback);
}
@Override public long optLong(int index, long fallback) {
arrayOptTypeCalls++;
return super.optLong(index, fallback);
}
@Override public String optString(int index, String fallback) {
arrayOptTypeCalls++;
return super.optString(index, fallback);
}
@Override public int optInt(int index, int fallback) {
arrayOptTypeCalls++;
return super.optInt(index, fallback);
}
};
private final JSONTokener tokener = new JSONTokener("{\"foo\": [true]}") {
@Override public char next() {
tokenerNextCalls++;
return super.next();
}
@Override public Object nextValue() throws JSONException {
tokenerNextValueCalls++;
return super.nextValue();
}
};
public void testObjectPut() throws JSONException {
object.putOpt("foo", "bar");
assertEquals(1, objectPutCalls);
}
public void testObjectAccumulate() throws JSONException {
object.accumulate("foo", "bar");
assertEquals(1, objectPutCalls);
}
public void testObjectGetBoolean() throws JSONException {
object.put("foo", "true");
object.getBoolean("foo");
assertEquals(1, objectGetCalls);
}
public void testObjectOptType() throws JSONException {
object.optBoolean("foo");
assertEquals(1, objectOptCalls);
assertEquals(1, objectOptTypeCalls);
object.optDouble("foo");
assertEquals(2, objectOptCalls);
assertEquals(2, objectOptTypeCalls);
object.optInt("foo");
assertEquals(3, objectOptCalls);
assertEquals(3, objectOptTypeCalls);
object.optLong("foo");
assertEquals(4, objectOptCalls);
assertEquals(4, objectOptTypeCalls);
object.optString("foo");
assertEquals(5, objectOptCalls);
assertEquals(5, objectOptTypeCalls);
}
public void testToJSONArray() throws JSONException {
object.put("foo", 5);
object.put("bar", 10);
array.put("foo");
array.put("baz");
array.put("bar");
object.toJSONArray(array);
assertEquals(3, arrayOptCalls);
assertEquals(0, arrayOptTypeCalls);
assertEquals(3, objectOptCalls);
assertEquals(0, objectOptTypeCalls);
}
public void testPutAtIndex() throws JSONException {
array.put(10, false);
assertEquals(1, arrayPutCalls);
}
public void testIsNull() {
array.isNull(5);
assertEquals(1, arrayOptCalls);
}
public void testArrayGetType() throws JSONException {
array.put(true);
array.getBoolean(0);
assertEquals(1, arrayGetCalls);
}
public void testArrayOptType() throws JSONException {
array.optBoolean(3);
assertEquals(1, arrayOptCalls);
assertEquals(1, arrayOptTypeCalls);
array.optDouble(3);
assertEquals(2, arrayOptCalls);
assertEquals(2, arrayOptTypeCalls);
array.optInt(3);
assertEquals(3, arrayOptCalls);
assertEquals(3, arrayOptTypeCalls);
array.optLong(3);
assertEquals(4, arrayOptCalls);
assertEquals(4, arrayOptTypeCalls);
array.optString(3);
assertEquals(5, arrayOptCalls);
assertEquals(5, arrayOptTypeCalls);
}
public void testToJSONObject() throws JSONException {
array.put("foo");
array.put("baz");
array.put("bar");
JSONArray values = new JSONArray();
values.put(5.5d);
values.put(11d);
values.put(30);
values.toJSONObject(array);
assertEquals(3, arrayOptCalls);
assertEquals(0, arrayOptTypeCalls);
}
public void testNextExpecting() throws JSONException {
tokener.next('{');
assertEquals(1, tokenerNextCalls);
tokener.next('\"');
assertEquals(2, tokenerNextCalls);
}
public void testNextValue() throws JSONException {
tokener.nextValue();
assertEquals(4, tokenerNextValueCalls);
}
}