pax_global_header00006660000000000000000000000064120713601350014510gustar00rootroot0000000000000052 comment=34468a2cd4c6987eee38240e87e144825dfda7cb libandroid-json-org-java-20121204-20090211/000077500000000000000000000000001207136013500174235ustar00rootroot00000000000000libandroid-json-org-java-20121204-20090211/src/000077500000000000000000000000001207136013500202125ustar00rootroot00000000000000libandroid-json-org-java-20121204-20090211/src/main/000077500000000000000000000000001207136013500211365ustar00rootroot00000000000000libandroid-json-org-java-20121204-20090211/src/main/java/000077500000000000000000000000001207136013500220575ustar00rootroot00000000000000libandroid-json-org-java-20121204-20090211/src/main/java/org/000077500000000000000000000000001207136013500226465ustar00rootroot00000000000000libandroid-json-org-java-20121204-20090211/src/main/java/org/json/000077500000000000000000000000001207136013500236175ustar00rootroot00000000000000libandroid-json-org-java-20121204-20090211/src/main/java/org/json/JSON.java000066400000000000000000000074541207136013500252450ustar00rootroot00000000000000/* * 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.java000066400000000000000000000456731207136013500262510ustar00rootroot00000000000000/* * 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.java000066400000000000000000000031641207136013500271160ustar00rootroot00000000000000/* * 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.java000066400000000000000000000606441207136013500263740ustar00rootroot00000000000000/* * 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.java000066400000000000000000000316021207136013500267530ustar00rootroot00000000000000/* * 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.java000066400000000000000000000502441207136013500265700ustar00rootroot00000000000000/* * 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/000077500000000000000000000000001207136013500211715ustar00rootroot00000000000000libandroid-json-org-java-20121204-20090211/src/test/java/000077500000000000000000000000001207136013500221125ustar00rootroot00000000000000libandroid-json-org-java-20121204-20090211/src/test/java/org/000077500000000000000000000000001207136013500227015ustar00rootroot00000000000000libandroid-json-org-java-20121204-20090211/src/test/java/org/json/000077500000000000000000000000001207136013500236525ustar00rootroot00000000000000libandroid-json-org-java-20121204-20090211/src/test/java/org/json/JSONArrayTest.java000066400000000000000000000444571207136013500271430ustar00rootroot00000000000000/* * 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.java000066400000000000000000001007431207136013500272620ustar00rootroot00000000000000/* * 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.java000066400000000000000000000270061207136013500276510ustar00rootroot00000000000000/* * 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.java000066400000000000000000000552661207136013500274740ustar00rootroot00000000000000/* * 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.java000066400000000000000000000242441207136013500267660ustar00rootroot00000000000000/* * 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.java000066400000000000000000000170271207136013500267320ustar00rootroot00000000000000/* * 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); } }