http://git-wip-us.apache.org/repos/asf/geode/blob/b3ec80bc/geode-json/src/main/java/org/json/JSONArray.java ---------------------------------------------------------------------- diff --git a/geode-json/src/main/java/org/json/JSONArray.java b/geode-json/src/main/java/org/json/JSONArray.java old mode 100644 new mode 100755 index edaefa4..074624d --- a/geode-json/src/main/java/org/json/JSONArray.java +++ b/geode-json/src/main/java/org/json/JSONArray.java @@ -1,868 +1,759 @@ -package org.json; - /* - * Copyright (c) 2002 JSON.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - * associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * The Software shall be used for Good, not Evil. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * 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. */ -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; +package org.json; + import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; -import java.util.Map; +import java.util.List; + +// Note: this class was written without inspecting the non-free org.json sourcecode. /** - * A JSONArray is an ordered sequence of values. Its external text form is a string wrapped in - * square brackets with commas separating the values. The internal form is an object having - * <code>get</code> and <code>opt</code> methods for accessing the values by index, and - * <code>put</code> methods for adding or replacing values. The values can be any of these types: - * <code>Boolean</code>, <code>JSONArray</code>, <code>JSONObject</code>, <code>Number</code>, - * <code>String</code>, or the <code>JSONObject.NULL object</code>. - * <p> - * The constructor can convert a JSON text into a Java object. The <code>toString</code> method - * converts to JSON text. - * <p> - * A <code>get</code> method returns a value if one can be found, and throws an exception if one - * cannot be found. An <code>opt</code> method returns a default value instead of throwing an - * exception, and so is useful for obtaining optional values. - * <p> - * The generic <code>get()</code> and <code>opt()</code> methods return an object which you can cast - * or query for type. There are also typed <code>get</code> and <code>opt</code> methods that do - * type checking and type coercion for you. - * <p> - * The texts produced by the <code>toString</code> methods strictly conform to JSON syntax rules. - * The constructors are more forgiving in the texts they will accept: - * <ul> - * <li>An extra <code>,</code> <small>(comma)</small> may appear just before the closing - * bracket.</li> - * <li>The <code>null</code> value will be inserted when there is <code>,</code> - * <small>(comma)</small> elision.</li> - * <li>Strings may be quoted with <code>'</code> <small>(single quote)</small>.</li> - * <li>Strings do not need to be quoted at all if they do not begin with a quote or single quote, - * and if they do not contain leading or trailing spaces, and if they do not contain any of these - * characters: <code>{ } [ ] / \ : , = ; #</code> and if they do not look like numbers and if they - * are not the reserved words <code>true</code>, <code>false</code>, or <code>null</code>.</li> - * <li>Values can be separated by <code>;</code> <small>(semicolon)</small> as well as by - * <code>,</code> <small>(comma)</small>.</li> - * </ul> + * 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. * - * @author JSON.org - * @version 2012-04-20 + * <strong>Warning:</strong> 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 + * non-final, it was not designed for inheritance and should not be subclassed. + * In particular, self-use by overridable methods is not specified. See + * <i>Effective Java</i> Item 17, "Design and Document or inheritance or else + * prohibit it" for further information. */ public class JSONArray { + private final List<Object> values; + + /** + * Creates a {@code JSONArray} with no values. + */ + public JSONArray() { + values = new ArrayList<Object>(); + } + + /** + * 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(); + if (copyFrom != null) { + for (Object aCopyFrom : copyFrom) { + put(JSONObject.wrap(aCopyFrom)); + } + } + } + + /** + * 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)); + } + + /** + * Creates a new {@code JSONArray} with values from the given primitive array. + * + * @param array The values to use. + * @throws JSONException if any of the values are non-finite double values (i.e. NaN or infinite) + */ + public JSONArray(Object array) throws JSONException { + if (!array.getClass().isArray()) { + throw new JSONException("Not a primitive array: " + array.getClass()); + } + final int length = Array.getLength(array); + values = new ArrayList<Object>(length); + for (int i = 0; i < length; ++i) { + put(JSONObject.wrap(Array.get(array, i))); + } + } + + /** + * @return Returns the number of values in this array. + */ + public int length() { + return values.size(); + } + + /** + * Appends {@code value} to the end of this array. + * + * @param value The value to append. + * @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. + * @throws JSONException If the value is unacceptable. + */ + public JSONArray put(double value) throws JSONException { + values.add(JSON.checkDouble(value)); + return this; + } + + /** + * Appends {@code value} to the end of this array. + * + * @param value The value to append. + * @return this array. + */ + public JSONArray put(int value) { + values.add(value); + return this; + } + + /** + * Appends {@code value} to the end of this array. + * + * @param value The value to append. + * @return this array. + */ + public JSONArray put(long value) { + values.add(value); + return this; + } + + /** + * Appends {@code value} wrapped by {@link JSONArray} to the end of this array. + * + * @param value any collection. + * @return this array. + */ + public JSONArray put(Collection<?> value) { + if (value == null) { + return put((Object)null); + } + values.add(new JSONArray(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; + } + + /** + * Same as {@link #put}, with added validity checks. + * + * @param value The value to append. + */ + void checkedPut(Object value) throws JSONException { + if (value instanceof Number) { + JSON.checkDouble(((Number) value).doubleValue()); + } + + put(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 index Where to put the value. + * @param value The value to set. + * @return this array. + * @throws JSONException This should never happen. + */ + 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 index Where to put the value. + * @param value a finite value. May not be {@link Double#isNaN() NaNs} or + * {@link Double#isInfinite() infinities}. + * @return this array. + * @throws JSONException If the value is not a finite value. + */ + 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. + * + * @param index Where to put the value. + * @param value The value to set. + * @return this array. + * @throws JSONException Should never actually happen. + */ + 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. + * + * @param index Where to put the value. + * @param value The value to set. + * @return this array. + * @throws JSONException Should never actually happen. + */ + public JSONArray put(int index, long value) throws JSONException { + return put(index, (Long) value); + } + + /** + * Sets the value at {@code index} to {@code value} wrapped into {@link JSONArray}, + * null padding this array to the required length if necessary. If a value already + * exists at {@code index}, it will be replaced. + * + * @param index Where to put the value. + * @param value The value to set. + * @return this array. + * @throws JSONException Should never actually happen. + */ + public JSONArray put(int index, Collection<?> value) throws JSONException { + if (value == null) { + return put(index, (Object)null); + } + return put(index, new JSONArray(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 index Where to put the value. + * @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. + * @throws JSONException If the value cannot be represented as a finite double value. + */ + 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}. + * + * @param index Which value to check. + * @return true if the value is null. + */ + public boolean isNull(int index) { + Object value = opt(index); + return value == null || value == JSONObject.NULL; + } + + /** + * Returns the value at {@code index}. + * + * @param index Which value to get. + * @return the value at the specified location. + * @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}. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + public Object opt(int index) { + if (index < 0 || index >= values.size()) { + return null; + } + return values.get(index); + } + + /** + * Removes and returns the value at {@code index}, or null if the array has no value + * at {@code index}. + * + * @param index Which value to remove. + * @return The value previously at the specified location. + */ + public Object remove(int index) { + if (index < 0 || index >= values.size()) { + return null; + } + return values.remove(index); + } + + /** + * Returns the value at {@code index} if it exists and is a boolean or can + * be coerced to a boolean. + * + * @param index Which value to get. + * @return the value at the specified location. + * @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. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + 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. + * + * @param index Which value to get. + * @param fallback the fallback value to return if no value exists. + * @return the value at the specified location or the fallback value. + */ + 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. + * + * @param index Which value to get. + * @return the value at the specified location. + * @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. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + 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. + * + * @param index Which value to get. + * @param fallback The fallback value to use if no value is at the specified location. + * @return the value at the specified location or the fallback value. + */ + 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. + * + * @param index Which value to get. + * @return the value at the specified location. + * @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. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + 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. + * + * @param index Which value to get. + * @param fallback The fallback value to use if no value is at the specified location. + * @return the value at the specified location or the fallback value. + */ + 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. + * + * @param index Which value to get. + * @return the value at the specified location. + * @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. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + 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. + * + * @param index Which value to get. + * @param fallback The fallback value to use if no value is at the specified location. + * @return the value at the specified location or the fallback value. + */ + public long optLong(int index, long fallback) { + Object object = opt(index); + Long result = JSON.toLong(object); + return result != null ? result : fallback; + } - /** - * The arrayList where the JSONArray's properties are kept. - */ - private final ArrayList myArrayList; - - - /** - * Construct an empty JSONArray. - */ - public JSONArray() { - this.myArrayList = new ArrayList(); - } - - /** - * Construct a JSONArray from a JSONTokener. - * - * @param x A JSONTokener - * @throws JSONException If there is a syntax error. - */ - public JSONArray(JSONTokener x) throws JSONException { - this(); - if (x.nextClean() != '[') { - throw x.syntaxError("A JSONArray text must start with '['"); - } - if (x.nextClean() != ']') { - x.back(); - for (;;) { - if (x.nextClean() == ',') { - x.back(); - this.myArrayList.add(JSONObject.NULL); + /** + * Returns the value at {@code index} if it exists, coercing it if + * necessary. + * + * @param index Which value to get. + * @return the value at the specified location. + * @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. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + 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. + * + * @param index Which value to get. + * @param fallback The fallback value to use if no value is at the specified location. + * @return the value at the specified location or the fallback value. + */ + 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}. + * + * @param index Which value to get. + * @return the value at the specified location. + * @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 { - x.back(); - this.myArrayList.add(x.nextValue()); + throw JSON.typeMismatch(index, object, "JSONArray"); } - switch (x.nextClean()) { - case ';': - case ',': - if (x.nextClean() == ']') { - return; + } + + /** + * Returns the value at {@code index} if it exists and is a {@code + * JSONArray}. Returns null otherwise. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + 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}. + * + * @param index Which value to get. + * @return the value at the specified location. + * @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. + * + * @param index Which value to get. + * @return the value at the specified location. + */ + 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. + * + * @param names The names to apply to the returned values. + * @return the newly constructed object. + * @throws JSONException Should not be possible. + */ + 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: + * <pre>"12\" pizza"+"taco"+"soda"</pre> + * + * @param separator The string used to separate the returned values. + * @return the conjoined values. + * @throws JSONException Only if there is a coding error. + */ + 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); } - x.back(); - break; - case ']': - return; - default: - throw x.syntaxError("Expected a ',' or ']'"); + stringer.value(values.get(i)); } - } - } - } - - - /** - * Construct a JSONArray from a source JSON text. - * - * @param source A string that begins with <code>[</code> <small>(left bracket)</small> and - * ends with <code>]</code> <small>(right bracket)</small>. - * @throws JSONException If there is a syntax error. - */ - public JSONArray(String source) throws JSONException { - this(new JSONTokener(source)); - } - - - /** - * Construct a JSONArray from a Collection. - * - * @param collection A Collection. - */ - public JSONArray(Collection collection) { - this.myArrayList = new ArrayList(); - if (collection != null) { - Iterator iter = collection.iterator(); - while (iter.hasNext()) { - this.myArrayList.add(JSONObject.wrap(iter.next())); - } - } - } - - - /** - * Construct a JSONArray from an array - * - * @throws JSONException If not an array. - */ - public JSONArray(Object array) throws JSONException { - this(); - if (array.getClass().isArray()) { - int length = Array.getLength(array); - for (int i = 0; i < length; i += 1) { - this.put(JSONObject.wrap(Array.get(array, i))); - } - } else { - throw new JSONException("JSONArray initial value should be a string or collection or array."); - } - } - - - /** - * Get the object value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return An object value. - * @throws JSONException If there is no value for the index. - */ - public Object get(int index) throws JSONException { - Object object = this.opt(index); - if (object == null) { - throw new JSONException("JSONArray[" + index + "] not found."); - } - return object; - } - - - /** - * Get the boolean value associated with an index. The string values "true" and "false" are - * converted to boolean. - * - * @param index The index must be between 0 and length() - 1. - * @return The truth. - * @throws JSONException If there is no value for the index or if the value is not convertible to - * boolean. - */ - public boolean getBoolean(int index) throws JSONException { - Object object = this.get(index); - if (object.equals(Boolean.FALSE) - || (object instanceof String && ((String) object).equalsIgnoreCase("false"))) { - return false; - } else if (object.equals(Boolean.TRUE) - || (object instanceof String && ((String) object).equalsIgnoreCase("true"))) { - return true; - } - throw new JSONException("JSONArray[" + index + "] is not a boolean."); - } - - - /** - * Get the double value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException If the key is not found or if the value cannot be converted to a number. - */ - public double getDouble(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number ? ((Number) object).doubleValue() - : Double.parseDouble((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number."); - } - } - - - /** - * Get the int value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException If the key is not found or if the value is not a number. - */ - public int getInt(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number ? ((Number) object).intValue() - : Integer.parseInt((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number."); - } - } - - - /** - * Get the JSONArray associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return A JSONArray value. - * @throws JSONException If there is no value for the index. or if the value is not a JSONArray - */ - public JSONArray getJSONArray(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONArray) { - return (JSONArray) object; - } - throw new JSONException("JSONArray[" + index + "] is not a JSONArray."); - } - - - /** - * Get the JSONObject associated with an index. - * - * @param index subscript - * @return A JSONObject value. - * @throws JSONException If there is no value for the index or if the value is not a JSONObject - */ - public JSONObject getJSONObject(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONObject) { - return (JSONObject) object; - } - throw new JSONException("JSONArray[" + index + "] is not a JSONObject."); - } - - - /** - * Get the long value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - * @throws JSONException If the key is not found or if the value cannot be converted to a number. - */ - public long getLong(int index) throws JSONException { - Object object = this.get(index); - try { - return object instanceof Number ? ((Number) object).longValue() - : Long.parseLong((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number."); - } - } - - - /** - * Get the string associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return A string value. - * @throws JSONException If there is no string value for the index. - */ - public String getString(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof String) { - return (String) object; - } - throw new JSONException("JSONArray[" + index + "] not a string."); - } - - - /** - * Determine if the value is null. - * - * @param index The index must be between 0 and length() - 1. - * @return true if the value at the index is null, or if there is no value. - */ - public boolean isNull(int index) { - return JSONObject.NULL.equals(this.opt(index)); - } - - - /** - * Make a string from the contents of this JSONArray. The <code>separator</code> string is - * inserted between each element. Warning: This method assumes that the data structure is - * acyclical. - * - * @param separator A string that will be inserted between the elements. - * @return a string. - * @throws JSONException If the array contains an invalid number. - */ - public String join(String separator) throws JSONException { - int len = this.length(); - StringBuffer sb = new StringBuffer(); - - for (int i = 0; i < len; i += 1) { - if (i > 0) { - sb.append(separator); - } - sb.append(JSONObject.valueToString(this.myArrayList.get(i))); - } - return sb.toString(); - } - - - /** - * Get the number of elements in the JSONArray, included nulls. - * - * @return The length (or size). - */ - public int length() { - return this.myArrayList.size(); - } - - - /** - * Get the optional object value associated with an index. - * - * @param index The index must be between 0 and length() - 1. - * @return An object value, or null if there is no object at that index. - */ - public Object opt(int index) { - return (index < 0 || index >= this.length()) ? null : this.myArrayList.get(index); - } - - - /** - * Get the optional boolean value associated with an index. It returns false if there is no value - * at that index, or if the value is not Boolean.TRUE or the String "true". - * - * @param index The index must be between 0 and length() - 1. - * @return The truth. - */ - public boolean optBoolean(int index) { - return this.optBoolean(index, false); - } - - - /** - * Get the optional boolean value associated with an index. It returns the defaultValue if there - * is no value at that index or if it is not a Boolean or the String "true" or "false" (case - * insensitive). - * - * @param index The index must be between 0 and length() - 1. - * @param defaultValue A boolean default. - * @return The truth. - */ - public boolean optBoolean(int index, boolean defaultValue) { - try { - return this.getBoolean(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional double value associated with an index. NaN is returned if there is no value - * for the index, or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - */ - public double optDouble(int index) { - return this.optDouble(index, Double.NaN); - } - - - /** - * Get the optional double value associated with an index. The defaultValue is returned if there - * is no value for the index, or if the value is not a number and cannot be converted to a number. - * - * @param index subscript - * @param defaultValue The default value. - * @return The value. - */ - public double optDouble(int index, double defaultValue) { - try { - return this.getDouble(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional int value associated with an index. Zero is returned if there is no value for - * the index, or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - */ - public int optInt(int index) { - return this.optInt(index, 0); - } - - - /** - * Get the optional int value associated with an index. The defaultValue is returned if there is - * no value for the index, or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return The value. - */ - public int optInt(int index, int defaultValue) { - try { - return this.getInt(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional JSONArray associated with an index. - * - * @param index subscript - * @return A JSONArray value, or null if the index has no value, or if the value is not a - * JSONArray. - */ - public JSONArray optJSONArray(int index) { - Object o = this.opt(index); - return o instanceof JSONArray ? (JSONArray) o : null; - } - - - /** - * Get the optional JSONObject associated with an index. Null is returned if the key is not found, - * or null if the index has no value, or if the value is not a JSONObject. - * - * @param index The index must be between 0 and length() - 1. - * @return A JSONObject value. - */ - public JSONObject optJSONObject(int index) { - Object o = this.opt(index); - return o instanceof JSONObject ? (JSONObject) o : null; - } - - - /** - * Get the optional long value associated with an index. Zero is returned if there is no value for - * the index, or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @return The value. - */ - public long optLong(int index) { - return this.optLong(index, 0); - } - - - /** - * Get the optional long value associated with an index. The defaultValue is returned if there is - * no value for the index, or if the value is not a number and cannot be converted to a number. - * - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return The value. - */ - public long optLong(int index, long defaultValue) { - try { - return this.getLong(index); - } catch (Exception e) { - return defaultValue; - } - } - - - /** - * Get the optional string value associated with an index. It returns an empty string if there is - * no value at that index. If the value is not a string and is not null, then it is coverted to a - * string. - * - * @param index The index must be between 0 and length() - 1. - * @return A String value. - */ - public String optString(int index) { - return this.optString(index, ""); - } - - - /** - * Get the optional string associated with an index. The defaultValue is returned if the key is - * not found. - * - * @param index The index must be between 0 and length() - 1. - * @param defaultValue The default value. - * @return A String value. - */ - public String optString(int index, String defaultValue) { - Object object = this.opt(index); - return JSONObject.NULL.equals(object) ? defaultValue : object.toString(); - } - - - /** - * Append a boolean value. This increases the array's length by one. - * - * @param value A boolean value. - * @return this. - */ - public JSONArray put(boolean value) { - this.put(value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a JSONArray which is produced from a - * Collection. - * - * @param value A Collection value. - * @return this. - */ - public JSONArray put(Collection value) { - this.put(new JSONArray(value)); - return this; - } - - - /** - * Append a double value. This increases the array's length by one. - * - * @param value A double value. - * @throws JSONException if the value is not finite. - * @return this. - */ - public JSONArray put(double value) throws JSONException { - Double d = new Double(value); - JSONObject.testValidity(d); - this.put(d); - return this; - } - - - /** - * Append an int value. This increases the array's length by one. - * - * @param value An int value. - * @return this. - */ - public JSONArray put(int value) { - this.put(new Integer(value)); - return this; - } - - - /** - * Append an long value. This increases the array's length by one. - * - * @param value A long value. - * @return this. - */ - public JSONArray put(long value) { - this.put(new Long(value)); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a JSONObject which is produced from a - * Map. - * - * @param value A Map value. - * @return this. - */ - public JSONArray put(Map value) { - this.put(new JSONObject(value)); - return this; - } - - - /** - * Append an object value. This increases the array's length by one. - * - * @param value An object value. The value should be a Boolean, Double, Integer, JSONArray, - * JSONObject, Long, or String, or the JSONObject.NULL object. - * @return this. - */ - public JSONArray put(Object value) { - this.myArrayList.add(value); - return this; - } - - - /** - * Put or replace a boolean value in the JSONArray. If the index is greater than the length of the - * JSONArray, then null elements will be added as necessary to pad it out. - * - * @param index The subscript. - * @param value A boolean value. - * @return this. - * @throws JSONException If the index is negative. - */ - public JSONArray put(int index, boolean value) throws JSONException { - this.put(index, value ? Boolean.TRUE : Boolean.FALSE); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a JSONArray which is produced from a - * Collection. - * - * @param index The subscript. - * @param value A Collection value. - * @return this. - * @throws JSONException If the index is negative or if the value is not finite. - */ - public JSONArray put(int index, Collection value) throws JSONException { - this.put(index, new JSONArray(value)); - return this; - } - - - /** - * Put or replace a double value. If the index is greater than the length of the JSONArray, then - * null elements will be added as necessary to pad it out. - * - * @param index The subscript. - * @param value A double value. - * @return this. - * @throws JSONException If the index is negative or if the value is not finite. - */ - public JSONArray put(int index, double value) throws JSONException { - this.put(index, new Double(value)); - return this; - } - - - /** - * Put or replace an int value. If the index is greater than the length of the JSONArray, then - * null elements will be added as necessary to pad it out. - * - * @param index The subscript. - * @param value An int value. - * @return this. - * @throws JSONException If the index is negative. - */ - public JSONArray put(int index, int value) throws JSONException { - this.put(index, new Integer(value)); - return this; - } - - - /** - * Put or replace a long value. If the index is greater than the length of the JSONArray, then - * null elements will be added as necessary to pad it out. - * - * @param index The subscript. - * @param value A long value. - * @return this. - * @throws JSONException If the index is negative. - */ - public JSONArray put(int index, long value) throws JSONException { - this.put(index, new Long(value)); - return this; - } - - - /** - * Put a value in the JSONArray, where the value will be a JSONObject that is produced from a Map. - * - * @param index The subscript. - * @param value The Map value. - * @return this. - * @throws JSONException If the index is negative or if the the value is an invalid number. - */ - public JSONArray put(int index, Map value) throws JSONException { - this.put(index, new JSONObject(value)); - return this; - } - - - /** - * Put or replace an object value in the JSONArray. If the index is greater than the length of the - * JSONArray, then null elements will be added as necessary to pad it out. - * - * @param index The subscript. - * @param value The value to put into the array. The value should be a Boolean, Double, Integer, - * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. - * @return this. - * @throws JSONException If the index is negative or if the the value is an invalid number. - */ - public JSONArray put(int index, Object value) throws JSONException { - JSONObject.testValidity(value); - if (index < 0) { - throw new JSONException("JSONArray[" + index + "] not found."); - } - if (index < this.length()) { - this.myArrayList.set(index, value); - } else { - while (index != this.length()) { - this.put(JSONObject.NULL); - } - this.put(value); - } - return this; - } - - - /** - * Remove an index and close the hole. - * - * @param index The index of the element to be removed. - * @return The value that was associated with the index, or null if there was no value. - */ - public Object remove(int index) { - Object o = this.opt(index); - this.myArrayList.remove(index); - return o; - } - - - /** - * Produce a JSONObject by combining a JSONArray of names with the values of this JSONArray. - * - * @param names A JSONArray containing a list of key strings. These will be paired with the - * values. - * @return A JSONObject, or null if there are no names or if this JSONArray has no values. - * @throws JSONException If any of the names are null. - */ - public JSONObject toJSONObject(JSONArray names) throws JSONException { - if (names == null || names.length() == 0 || this.length() == 0) { - return null; - } - JSONObject jo = new JSONObject(); - for (int i = 0; i < names.length(); i += 1) { - jo.put(names.getString(i), this.opt(i)); - } - return jo; - } - - - /** - * Make a JSON text of this JSONArray. For compactness, no unnecessary whitespace is added. If it - * is not possible to produce a syntactically correct JSON text then null will be returned - * instead. This could occur if the array contains an invalid number. - * <p> - * Warning: This method assumes that the data structure is acyclical. - * - * @return a printable, displayable, transmittable representation of the array. - */ - public String toString() { - try { - return '[' + this.join(",") + ']'; - } catch (Exception e) { - return null; - } - } - - - /** - * Make a prettyprinted JSON text of this JSONArray. Warning: This method assumes that the data - * structure is acyclical. - * - * @param indentFactor The number of spaces to add to each level of indentation. - * @return a printable, displayable, transmittable representation of the object, beginning with - * <code>[</code> <small>(left bracket)</small> and ending with - * <code>]</code> <small>(right bracket)</small>. - * @throws JSONException - */ - public String toString(int indentFactor) throws JSONException { - StringWriter sw = new StringWriter(); - synchronized (sw.getBuffer()) { - return this.write(sw, indentFactor, 0).toString(); - } - } - - /** - * Write the contents of the JSONArray as JSON text to a writer. For compactness, no whitespace is - * added. - * <p> - * Warning: This method assumes that the data structure is acyclical. - * - * @return The writer. - * @throws JSONException - */ - public Writer write(Writer writer) throws JSONException { - return this.write(writer, 0, 0); - } - - /** - * Write the contents of the JSONArray as JSON text to a writer. For compactness, no whitespace is - * added. - * <p> - * Warning: This method assumes that the data structure is acyclical. - * - * @param indentFactor The number of spaces to add to each level of indentation. - * @param indent The indention of the top level. - * @return The writer. - * @throws JSONException - */ - Writer write(Writer writer, int indentFactor, int indent) throws JSONException { - try { - boolean commanate = false; - int length = this.length(); - writer.write('['); - - if (length == 1) { - JSONObject.writeValue(writer, this.myArrayList.get(0), indentFactor, indent); - } else if (length != 0) { - final int newindent = indent + indentFactor; - - for (int i = 0; i < length; i += 1) { - if (commanate) { - writer.write(','); - } - if (indentFactor > 0) { - writer.write('\n'); - } - JSONObject.indent(writer, newindent); - JSONObject.writeValue(writer, this.myArrayList.get(i), indentFactor, newindent); - commanate = true; + stringer.close(JSONStringer.Scope.NULL, JSONStringer.Scope.NULL, ""); + return stringer.out.toString(); + } + + /** + * Encodes this array as a compact JSON string, such as: + * <pre>[94043,90210]</pre> + * + * @return The string form of this array. + */ + @Override + public String toString() { + try { + JSONStringer stringer = new JSONStringer(); + writeTo(stringer); + return stringer.toString(); + } catch (JSONException e) { + return null; } - if (indentFactor > 0) { - writer.write('\n'); + } + + /** + * Encodes this array as a human readable JSON string for debugging, such + * as: + * <pre> + * [ + * 94043, + * 90210 + * ]</pre> + * + * @param indentSpaces the number of spaces to indent for each level of + * nesting. + * @return The string form of this array. + * @throws JSONException Only if there is a coding error. + */ + 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); } - JSONObject.indent(writer, indent); - } - writer.write(']'); - return writer; - } catch (IOException e) { - throw new JSONException(e); - } - } + 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(); + } }
http://git-wip-us.apache.org/repos/asf/geode/blob/b3ec80bc/geode-json/src/main/java/org/json/JSONException.java ---------------------------------------------------------------------- diff --git a/geode-json/src/main/java/org/json/JSONException.java b/geode-json/src/main/java/org/json/JSONException.java index b65efe2..1292e86 100755 --- a/geode-json/src/main/java/org/json/JSONException.java +++ b/geode-json/src/main/java/org/json/JSONException.java @@ -1,30 +1,57 @@ +/* + * 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. + /** - * The JSONException is thrown by the JSON.org classes when things are amiss. - * - * @author JSON.org - * @version 2010-12-24 + * Thrown to indicate a problem with the JSON API. Such problems include: + * <ul> + * <li>Attempts to parse or construct malformed documents + * <li>Use of null as a name + * <li>Use of numeric types not available to JSON, such as {@link + * Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}. + * <li>Lookups using an out of range index or nonexistent name + * <li>Type mismatches on lookups + * </ul> + * + * <p>Although this is a checked exception, it is rarely recoverable. Most + * callers should simply wrap this exception in an unchecked exception and + * rethrow: + * <pre> public JSONArray toJSONObject() { + * try { + * JSONObject result = new JSONObject(); + * ... + * } catch (JSONException e) { + * throw new RuntimeException(e); + * } + * }</pre> */ -public class JSONException extends Exception { - private static final long serialVersionUID = 0; - private Throwable cause; +public class JSONException extends RuntimeException { - /** - * Constructs a JSONException with an explanatory message. - * - * @param message Detail about the reason for the exception. - */ - public JSONException(String message) { - super(message); - } + public JSONException(String s) { + super(s); + } - public JSONException(Throwable cause) { - super(cause.getMessage()); - this.cause = cause; - } + public JSONException(Throwable cause) { + super(cause); + } - public Throwable getCause() { - return this.cause; - } + public JSONException(String message, Throwable cause) { + super(message, cause); + } } http://git-wip-us.apache.org/repos/asf/geode/blob/b3ec80bc/geode-json/src/main/java/org/json/JSONML.java ---------------------------------------------------------------------- diff --git a/geode-json/src/main/java/org/json/JSONML.java b/geode-json/src/main/java/org/json/JSONML.java deleted file mode 100755 index b535614..0000000 --- a/geode-json/src/main/java/org/json/JSONML.java +++ /dev/null @@ -1,454 +0,0 @@ -package org.json; - -/* - * Copyright (c) 2008 JSON.org - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - * associated documentation files (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, publish, distribute, - * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or - * substantial portions of the Software. - * - * The Software shall be used for Good, not Evil. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT - * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -import java.util.Iterator; - - -/** - * This provides static methods to convert an XML text into a JSONArray or JSONObject, and to covert - * a JSONArray or JSONObject into an XML text using the JsonML transform. - * - * @author JSON.org - * @version 2012-03-28 - */ -public class JSONML { - - /** - * Parse XML values and store them in a JSONArray. - * - * @param x The XMLTokener containing the source string. - * @param arrayForm true if array form, false if object form. - * @param ja The JSONArray that is containing the current tag or null if we are at the outermost - * level. - * @return A JSONArray if the value is the outermost tag, otherwise null. - * @throws JSONException - */ - private static Object parse(XMLTokener x, boolean arrayForm, JSONArray ja) throws JSONException { - String attribute; - char c; - String closeTag = null; - int i; - JSONArray newja = null; - JSONObject newjo = null; - Object token; - String tagName = null; - - // Test for and skip past these forms: - // <!-- ... --> - // <![ ... ]]> - // <! ... > - // <? ... ?> - - while (true) { - if (!x.more()) { - throw x.syntaxError("Bad XML"); - } - token = x.nextContent(); - if (token == XML.LT) { - token = x.nextToken(); - if (token instanceof Character) { - if (token == XML.SLASH) { - - // Close tag </ - - token = x.nextToken(); - if (!(token instanceof String)) { - throw new JSONException("Expected a closing name instead of '" + token + "'."); - } - if (x.nextToken() != XML.GT) { - throw x.syntaxError("Misshaped close tag"); - } - return token; - } else if (token == XML.BANG) { - - // <! - - c = x.next(); - if (c == '-') { - if (x.next() == '-') { - x.skipPast("-->"); - } else { - x.back(); - } - } else if (c == '[') { - token = x.nextToken(); - if (token.equals("CDATA") && x.next() == '[') { - if (ja != null) { - ja.put(x.nextCDATA()); - } - } else { - throw x.syntaxError("Expected 'CDATA['"); - } - } else { - i = 1; - do { - token = x.nextMeta(); - if (token == null) { - throw x.syntaxError("Missing '>' after '<!'."); - } else if (token == XML.LT) { - i += 1; - } else if (token == XML.GT) { - i -= 1; - } - } while (i > 0); - } - } else if (token == XML.QUEST) { - - // <? - - x.skipPast("?>"); - } else { - throw x.syntaxError("Misshaped tag"); - } - - // Open tag < - - } else { - if (!(token instanceof String)) { - throw x.syntaxError("Bad tagName '" + token + "'."); - } - tagName = (String) token; - newja = new JSONArray(); - newjo = new JSONObject(); - if (arrayForm) { - newja.put(tagName); - if (ja != null) { - ja.put(newja); - } - } else { - newjo.put("tagName", tagName); - if (ja != null) { - ja.put(newjo); - } - } - token = null; - for (;;) { - if (token == null) { - token = x.nextToken(); - } - if (token == null) { - throw x.syntaxError("Misshaped tag"); - } - if (!(token instanceof String)) { - break; - } - - // attribute = value - - attribute = (String) token; - if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) { - throw x.syntaxError("Reserved attribute."); - } - token = x.nextToken(); - if (token == XML.EQ) { - token = x.nextToken(); - if (!(token instanceof String)) { - throw x.syntaxError("Missing value"); - } - newjo.accumulate(attribute, XML.stringToValue((String) token)); - token = null; - } else { - newjo.accumulate(attribute, ""); - } - } - if (arrayForm && newjo.length() > 0) { - newja.put(newjo); - } - - // Empty tag <.../> - - if (token == XML.SLASH) { - if (x.nextToken() != XML.GT) { - throw x.syntaxError("Misshaped tag"); - } - if (ja == null) { - if (arrayForm) { - return newja; - } else { - return newjo; - } - } - - // Content, between <...> and </...> - - } else { - if (token != XML.GT) { - throw x.syntaxError("Misshaped tag"); - } - closeTag = (String) parse(x, arrayForm, newja); - if (closeTag != null) { - if (!closeTag.equals(tagName)) { - throw x.syntaxError("Mismatched '" + tagName + "' and '" + closeTag + "'"); - } - tagName = null; - if (!arrayForm && newja.length() > 0) { - newjo.put("childNodes", newja); - } - if (ja == null) { - if (arrayForm) { - return newja; - } else { - return newjo; - } - } - } - } - } - } else { - if (ja != null) { - ja.put(token instanceof String ? XML.stringToValue((String) token) : token); - } - } - } - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a JSONArray using the JsonML - * transform. Each XML tag is represented as a JSONArray in which the first element is the tag - * name. If the tag has attributes, then the second element will be JSONObject containing the - * name/value pairs. If the tag contains children, then strings and JSONArrays will represent the - * child tags. Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. - * - * @param string The source string. - * @return A JSONArray containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONArray toJSONArray(String string) throws JSONException { - return toJSONArray(new XMLTokener(string)); - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a JSONArray using the JsonML - * transform. Each XML tag is represented as a JSONArray in which the first element is the tag - * name. If the tag has attributes, then the second element will be JSONObject containing the - * name/value pairs. If the tag contains children, then strings and JSONArrays will represent the - * child content and tags. Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. - * - * @param x An XMLTokener. - * @return A JSONArray containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONArray toJSONArray(XMLTokener x) throws JSONException { - return (JSONArray) parse(x, true, null); - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a JSONObject using the JsonML - * transform. Each XML tag is represented as a JSONObject with a "tagName" property. If the tag - * has attributes, then the attributes will be in the JSONObject as properties. If the tag - * contains children, the object will have a "childNodes" property which will be an array of - * strings and JsonML JSONObjects. - * - * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. - * - * @param x An XMLTokener of the XML source text. - * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(XMLTokener x) throws JSONException { - return (JSONObject) parse(x, false, null); - } - - - /** - * Convert a well-formed (but not necessarily valid) XML string into a JSONObject using the JsonML - * transform. Each XML tag is represented as a JSONObject with a "tagName" property. If the tag - * has attributes, then the attributes will be in the JSONObject as properties. If the tag - * contains children, the object will have a "childNodes" property which will be an array of - * strings and JsonML JSONObjects. - * - * Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored. - * - * @param string The XML source text. - * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException - */ - public static JSONObject toJSONObject(String string) throws JSONException { - return toJSONObject(new XMLTokener(string)); - } - - - /** - * Reverse the JSONML transformation, making an XML text from a JSONArray. - * - * @param ja A JSONArray. - * @return An XML string. - * @throws JSONException - */ - public static String toString(JSONArray ja) throws JSONException { - int i; - JSONObject jo; - String key; - Iterator keys; - int length; - Object object; - StringBuffer sb = new StringBuffer(); - String tagName; - String value; - - // Emit <tagName - - tagName = ja.getString(0); - XML.noSpace(tagName); - tagName = XML.escape(tagName); - sb.append('<'); - sb.append(tagName); - - object = ja.opt(1); - if (object instanceof JSONObject) { - i = 2; - jo = (JSONObject) object; - - // Emit the attributes - - keys = jo.keys(); - while (keys.hasNext()) { - key = keys.next().toString(); - XML.noSpace(key); - value = jo.optString(key); - if (value != null) { - sb.append(' '); - sb.append(XML.escape(key)); - sb.append('='); - sb.append('"'); - sb.append(XML.escape(value)); - sb.append('"'); - } - } - } else { - i = 1; - } - - // Emit content in body - - length = ja.length(); - if (i >= length) { - sb.append('/'); - sb.append('>'); - } else { - sb.append('>'); - do { - object = ja.get(i); - i += 1; - if (object != null) { - if (object instanceof String) { - sb.append(XML.escape(object.toString())); - } else if (object instanceof JSONObject) { - sb.append(toString((JSONObject) object)); - } else if (object instanceof JSONArray) { - sb.append(toString((JSONArray) object)); - } - } - } while (i < length); - sb.append('<'); - sb.append('/'); - sb.append(tagName); - sb.append('>'); - } - return sb.toString(); - } - - /** - * Reverse the JSONML transformation, making an XML text from a JSONObject. The JSONObject must - * contain a "tagName" property. If it has children, then it must have a "childNodes" property - * containing an array of objects. The other properties are attributes with string values. - * - * @param jo A JSONObject. - * @return An XML string. - * @throws JSONException - */ - public static String toString(JSONObject jo) throws JSONException { - StringBuffer sb = new StringBuffer(); - int i; - JSONArray ja; - String key; - Iterator keys; - int length; - Object object; - String tagName; - String value; - - // Emit <tagName - - tagName = jo.optString("tagName"); - if (tagName == null) { - return XML.escape(jo.toString()); - } - XML.noSpace(tagName); - tagName = XML.escape(tagName); - sb.append('<'); - sb.append(tagName); - - // Emit the attributes - - keys = jo.keys(); - while (keys.hasNext()) { - key = keys.next().toString(); - if (!"tagName".equals(key) && !"childNodes".equals(key)) { - XML.noSpace(key); - value = jo.optString(key); - if (value != null) { - sb.append(' '); - sb.append(XML.escape(key)); - sb.append('='); - sb.append('"'); - sb.append(XML.escape(value)); - sb.append('"'); - } - } - } - - // Emit content in body - - ja = jo.optJSONArray("childNodes"); - if (ja == null) { - sb.append('/'); - sb.append('>'); - } else { - sb.append('>'); - length = ja.length(); - for (i = 0; i < length; i += 1) { - object = ja.get(i); - if (object != null) { - if (object instanceof String) { - sb.append(XML.escape(object.toString())); - } else if (object instanceof JSONObject) { - sb.append(toString((JSONObject) object)); - } else if (object instanceof JSONArray) { - sb.append(toString((JSONArray) object)); - } else { - sb.append(object.toString()); - } - } - } - sb.append('<'); - sb.append('/'); - sb.append(tagName); - sb.append('>'); - } - return sb.toString(); - } -}