Home | History | Annotate | Download | only in json
      1 package com.google.polo.json;
      2 
      3 /*
      4 Copyright (c) 2002 JSON.org
      5 
      6 Permission is hereby granted, free of charge, to any person obtaining a copy
      7 of this software and associated documentation files (the "Software"), to deal
      8 in the Software without restriction, including without limitation the rights
      9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10 copies of the Software, and to permit persons to whom the Software is
     11 furnished to do so, subject to the following conditions:
     12 
     13 The above copyright notice and this permission notice shall be included in all
     14 copies or substantial portions of the Software.
     15 
     16 The Software shall be used for Good, not Evil.
     17 
     18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     24 SOFTWARE.
     25 */
     26 
     27 import java.io.IOException;
     28 import java.io.Writer;
     29 import java.lang.reflect.Array;
     30 import java.util.ArrayList;
     31 import java.util.Collection;
     32 import java.util.Iterator;
     33 import java.util.Map;
     34 
     35 /**
     36  * A JSONArray is an ordered sequence of values. Its external text form is a
     37  * string wrapped in square brackets with commas separating the values. The
     38  * internal form is an object having <code>get</code> and <code>opt</code>
     39  * methods for accessing the values by index, and <code>put</code> methods for
     40  * adding or replacing values. The values can be any of these types:
     41  * <code>Boolean</code>, <code>JSONArray</code>, <code>JSONObject</code>,
     42  * <code>Number</code>, <code>String</code>, or the
     43  * <code>JSONObject.NULL object</code>.
     44  * <p>
     45  * The constructor can convert a JSON text into a Java object. The
     46  * <code>toString</code> method converts to JSON text.
     47  * <p>
     48  * A <code>get</code> method returns a value if one can be found, and throws an
     49  * exception if one cannot be found. An <code>opt</code> method returns a
     50  * default value instead of throwing an exception, and so is useful for
     51  * obtaining optional values.
     52  * <p>
     53  * The generic <code>get()</code> and <code>opt()</code> methods return an
     54  * object which you can cast or query for type. There are also typed
     55  * <code>get</code> and <code>opt</code> methods that do type checking and type
     56  * coercion for you.
     57  * <p>
     58  * The texts produced by the <code>toString</code> methods strictly conform to
     59  * JSON syntax rules. The constructors are more forgiving in the texts they will
     60  * accept:
     61  * <ul>
     62  * <li>An extra <code>,</code>&nbsp;<small>(comma)</small> may appear just
     63  *     before the closing bracket.</li>
     64  * <li>The <code>null</code> value will be inserted when there
     65  *     is <code>,</code>&nbsp;<small>(comma)</small> elision.</li>
     66  * <li>Strings may be quoted with <code>'</code>&nbsp;<small>(single
     67  *     quote)</small>.</li>
     68  * <li>Strings do not need to be quoted at all if they do not begin with a quote
     69  *     or single quote, and if they do not contain leading or trailing spaces,
     70  *     and if they do not contain any of these characters:
     71  *     <code>{ } [ ] / \ : , = ; #</code> and if they do not look like numbers
     72  *     and if they are not the reserved words <code>true</code>,
     73  *     <code>false</code>, or <code>null</code>.</li>
     74  * <li>Values can be separated by <code>;</code> <small>(semicolon)</small> as
     75  *     well as by <code>,</code> <small>(comma)</small>.</li>
     76  * <li>Numbers may have the <code>0-</code> <small>(octal)</small> or
     77  *     <code>0x-</code> <small>(hex)</small> prefix.</li>
     78  * </ul>
     79 
     80  * @author JSON.org
     81  * @version 2009-04-13
     82  */
     83 public class JSONArray {
     84 
     85 
     86     /**
     87      * The arrayList where the JSONArray's properties are kept.
     88      */
     89     private ArrayList myArrayList;
     90 
     91 
     92     /**
     93      * Construct an empty JSONArray.
     94      */
     95     public JSONArray() {
     96         this.myArrayList = new ArrayList();
     97     }
     98 
     99     /**
    100      * Construct a JSONArray from a JSONTokener.
    101      * @param x A JSONTokener
    102      * @throws JSONException If there is a syntax error.
    103      */
    104     public JSONArray(JSONTokener x) throws JSONException {
    105         this();
    106         char c = x.nextClean();
    107         char q;
    108         if (c == '[') {
    109             q = ']';
    110         } else if (c == '(') {
    111             q = ')';
    112         } else {
    113             throw x.syntaxError("A JSONArray text must start with '['");
    114         }
    115         if (x.nextClean() == ']') {
    116             return;
    117         }
    118         x.back();
    119         for (;;) {
    120             if (x.nextClean() == ',') {
    121                 x.back();
    122                 this.myArrayList.add(null);
    123             } else {
    124                 x.back();
    125                 this.myArrayList.add(x.nextValue());
    126             }
    127             c = x.nextClean();
    128             switch (c) {
    129             case ';':
    130             case ',':
    131                 if (x.nextClean() == ']') {
    132                     return;
    133                 }
    134                 x.back();
    135                 break;
    136             case ']':
    137             case ')':
    138                 if (q != c) {
    139                     throw x.syntaxError("Expected a '" + new Character(q) + "'");
    140                 }
    141                 return;
    142             default:
    143                 throw x.syntaxError("Expected a ',' or ']'");
    144             }
    145         }
    146     }
    147 
    148 
    149     /**
    150      * Construct a JSONArray from a source JSON text.
    151      * @param source     A string that begins with
    152      * <code>[</code>&nbsp;<small>(left bracket)</small>
    153      *  and ends with <code>]</code>&nbsp;<small>(right bracket)</small>.
    154      *  @throws JSONException If there is a syntax error.
    155      */
    156     public JSONArray(String source) throws JSONException {
    157         this(new JSONTokener(source));
    158     }
    159 
    160 
    161     /**
    162      * Construct a JSONArray from a Collection.
    163      * @param collection     A Collection.
    164      */
    165     public JSONArray(Collection collection) {
    166         this.myArrayList = (collection == null) ?
    167             new ArrayList() :
    168             new ArrayList(collection);
    169     }
    170 
    171     /**
    172      * Construct a JSONArray from a collection of beans.
    173      * The collection should have Java Beans.
    174      *
    175      * @throws JSONException If not an array.
    176      */
    177 
    178     public JSONArray(Collection collection, boolean includeSuperClass) {
    179 		this.myArrayList = new ArrayList();
    180 		if (collection != null) {
    181 			Iterator iter = collection.iterator();;
    182 			while (iter.hasNext()) {
    183 			    Object o = iter.next();
    184 			    if (o instanceof Map) {
    185 			    	this.myArrayList.add(new JSONObject((Map)o, includeSuperClass));
    186 			    } else if (!JSONObject.isStandardProperty(o.getClass())) {
    187 			    	this.myArrayList.add(new JSONObject(o, includeSuperClass));
    188 			    } else {
    189                     this.myArrayList.add(o);
    190 				}
    191 			}
    192 		}
    193     }
    194 
    195 
    196     /**
    197      * Construct a JSONArray from an array
    198      * @throws JSONException If not an array.
    199      */
    200     public JSONArray(Object array) throws JSONException {
    201         this();
    202         if (array.getClass().isArray()) {
    203             int length = Array.getLength(array);
    204             for (int i = 0; i < length; i += 1) {
    205                 this.put(Array.get(array, i));
    206             }
    207         } else {
    208             throw new JSONException("JSONArray initial value should be a string or collection or array.");
    209         }
    210     }
    211 
    212     /**
    213      * Construct a JSONArray from an array with a bean.
    214      * The array should have Java Beans.
    215      *
    216      * @throws JSONException If not an array.
    217      */
    218     public JSONArray(Object array,boolean includeSuperClass) throws JSONException {
    219         this();
    220         if (array.getClass().isArray()) {
    221             int length = Array.getLength(array);
    222             for (int i = 0; i < length; i += 1) {
    223                 Object o = Array.get(array, i);
    224                 if (JSONObject.isStandardProperty(o.getClass())) {
    225                     this.myArrayList.add(o);
    226                 } else {
    227                     this.myArrayList.add(new JSONObject(o,includeSuperClass));
    228                 }
    229             }
    230         } else {
    231             throw new JSONException("JSONArray initial value should be a string or collection or array.");
    232         }
    233     }
    234 
    235 
    236 
    237     /**
    238      * Get the object value associated with an index.
    239      * @param index
    240      *  The index must be between 0 and length() - 1.
    241      * @return An object value.
    242      * @throws JSONException If there is no value for the index.
    243      */
    244     public Object get(int index) throws JSONException {
    245         Object o = opt(index);
    246         if (o == null) {
    247             throw new JSONException("JSONArray[" + index + "] not found.");
    248         }
    249         return o;
    250     }
    251 
    252 
    253     /**
    254      * Get the boolean value associated with an index.
    255      * The string values "true" and "false" are converted to boolean.
    256      *
    257      * @param index The index must be between 0 and length() - 1.
    258      * @return      The truth.
    259      * @throws JSONException If there is no value for the index or if the
    260      *  value is not convertable to boolean.
    261      */
    262     public boolean getBoolean(int index) throws JSONException {
    263         Object o = get(index);
    264         if (o.equals(Boolean.FALSE) ||
    265                 (o instanceof String &&
    266                 ((String)o).equalsIgnoreCase("false"))) {
    267             return false;
    268         } else if (o.equals(Boolean.TRUE) ||
    269                 (o instanceof String &&
    270                 ((String)o).equalsIgnoreCase("true"))) {
    271             return true;
    272         }
    273         throw new JSONException("JSONArray[" + index + "] is not a Boolean.");
    274     }
    275 
    276 
    277     /**
    278      * Get the double value associated with an index.
    279      *
    280      * @param index The index must be between 0 and length() - 1.
    281      * @return      The value.
    282      * @throws   JSONException If the key is not found or if the value cannot
    283      *  be converted to a number.
    284      */
    285     public double getDouble(int index) throws JSONException {
    286         Object o = get(index);
    287         try {
    288             return o instanceof Number ?
    289                 ((Number)o).doubleValue() :
    290                 Double.valueOf((String)o).doubleValue();
    291         } catch (Exception e) {
    292             throw new JSONException("JSONArray[" + index +
    293                 "] is not a number.");
    294         }
    295     }
    296 
    297 
    298     /**
    299      * Get the int value associated with an index.
    300      *
    301      * @param index The index must be between 0 and length() - 1.
    302      * @return      The value.
    303      * @throws   JSONException If the key is not found or if the value cannot
    304      *  be converted to a number.
    305      *  if the value cannot be converted to a number.
    306      */
    307     public int getInt(int index) throws JSONException {
    308         Object o = get(index);
    309         return o instanceof Number ?
    310                 ((Number)o).intValue() : (int)getDouble(index);
    311     }
    312 
    313 
    314     /**
    315      * Get the JSONArray associated with an index.
    316      * @param index The index must be between 0 and length() - 1.
    317      * @return      A JSONArray value.
    318      * @throws JSONException If there is no value for the index. or if the
    319      * value is not a JSONArray
    320      */
    321     public JSONArray getJSONArray(int index) throws JSONException {
    322         Object o = get(index);
    323         if (o instanceof JSONArray) {
    324             return (JSONArray)o;
    325         }
    326         throw new JSONException("JSONArray[" + index +
    327                 "] is not a JSONArray.");
    328     }
    329 
    330 
    331     /**
    332      * Get the JSONObject associated with an index.
    333      * @param index subscript
    334      * @return      A JSONObject value.
    335      * @throws JSONException If there is no value for the index or if the
    336      * value is not a JSONObject
    337      */
    338     public JSONObject getJSONObject(int index) throws JSONException {
    339         Object o = get(index);
    340         if (o instanceof JSONObject) {
    341             return (JSONObject)o;
    342         }
    343         throw new JSONException("JSONArray[" + index +
    344             "] is not a JSONObject.");
    345     }
    346 
    347 
    348     /**
    349      * Get the long value associated with an index.
    350      *
    351      * @param index The index must be between 0 and length() - 1.
    352      * @return      The value.
    353      * @throws   JSONException If the key is not found or if the value cannot
    354      *  be converted to a number.
    355      */
    356     public long getLong(int index) throws JSONException {
    357         Object o = get(index);
    358         return o instanceof Number ?
    359                 ((Number)o).longValue() : (long)getDouble(index);
    360     }
    361 
    362 
    363     /**
    364      * Get the string associated with an index.
    365      * @param index The index must be between 0 and length() - 1.
    366      * @return      A string value.
    367      * @throws JSONException If there is no value for the index.
    368      */
    369     public String getString(int index) throws JSONException {
    370         return get(index).toString();
    371     }
    372 
    373 
    374     /**
    375      * Determine if the value is null.
    376      * @param index The index must be between 0 and length() - 1.
    377      * @return true if the value at the index is null, or if there is no value.
    378      */
    379     public boolean isNull(int index) {
    380         return JSONObject.NULL.equals(opt(index));
    381     }
    382 
    383 
    384     /**
    385      * Make a string from the contents of this JSONArray. The
    386      * <code>separator</code> string is inserted between each element.
    387      * Warning: This method assumes that the data structure is acyclical.
    388      * @param separator A string that will be inserted between the elements.
    389      * @return a string.
    390      * @throws JSONException If the array contains an invalid number.
    391      */
    392     public String join(String separator) throws JSONException {
    393         int len = length();
    394         StringBuffer sb = new StringBuffer();
    395 
    396         for (int i = 0; i < len; i += 1) {
    397             if (i > 0) {
    398                 sb.append(separator);
    399             }
    400             sb.append(JSONObject.valueToString(this.myArrayList.get(i)));
    401         }
    402         return sb.toString();
    403     }
    404 
    405 
    406     /**
    407      * Get the number of elements in the JSONArray, included nulls.
    408      *
    409      * @return The length (or size).
    410      */
    411     public int length() {
    412         return this.myArrayList.size();
    413     }
    414 
    415 
    416     /**
    417      * Get the optional object value associated with an index.
    418      * @param index The index must be between 0 and length() - 1.
    419      * @return      An object value, or null if there is no
    420      *              object at that index.
    421      */
    422     public Object opt(int index) {
    423         return (index < 0 || index >= length()) ?
    424             null : this.myArrayList.get(index);
    425     }
    426 
    427 
    428     /**
    429      * Get the optional boolean value associated with an index.
    430      * It returns false if there is no value at that index,
    431      * or if the value is not Boolean.TRUE or the String "true".
    432      *
    433      * @param index The index must be between 0 and length() - 1.
    434      * @return      The truth.
    435      */
    436     public boolean optBoolean(int index)  {
    437         return optBoolean(index, false);
    438     }
    439 
    440 
    441     /**
    442      * Get the optional boolean value associated with an index.
    443      * It returns the defaultValue if there is no value at that index or if
    444      * it is not a Boolean or the String "true" or "false" (case insensitive).
    445      *
    446      * @param index The index must be between 0 and length() - 1.
    447      * @param defaultValue     A boolean default.
    448      * @return      The truth.
    449      */
    450     public boolean optBoolean(int index, boolean defaultValue)  {
    451         try {
    452             return getBoolean(index);
    453         } catch (Exception e) {
    454             return defaultValue;
    455         }
    456     }
    457 
    458 
    459     /**
    460      * Get the optional double value associated with an index.
    461      * NaN is returned if there is no value for the index,
    462      * or if the value is not a number and cannot be converted to a number.
    463      *
    464      * @param index The index must be between 0 and length() - 1.
    465      * @return      The value.
    466      */
    467     public double optDouble(int index) {
    468         return optDouble(index, Double.NaN);
    469     }
    470 
    471 
    472     /**
    473      * Get the optional double value associated with an index.
    474      * The defaultValue is returned if there is no value for the index,
    475      * or if the value is not a number and cannot be converted to a number.
    476      *
    477      * @param index subscript
    478      * @param defaultValue     The default value.
    479      * @return      The value.
    480      */
    481     public double optDouble(int index, double defaultValue) {
    482         try {
    483             return getDouble(index);
    484         } catch (Exception e) {
    485             return defaultValue;
    486         }
    487     }
    488 
    489 
    490     /**
    491      * Get the optional int value associated with an index.
    492      * Zero is returned if there is no value for the index,
    493      * or if the value is not a number and cannot be converted to a number.
    494      *
    495      * @param index The index must be between 0 and length() - 1.
    496      * @return      The value.
    497      */
    498     public int optInt(int index) {
    499         return optInt(index, 0);
    500     }
    501 
    502 
    503     /**
    504      * Get the optional int value associated with an index.
    505      * The defaultValue is returned if there is no value for the index,
    506      * or if the value is not a number and cannot be converted to a number.
    507      * @param index The index must be between 0 and length() - 1.
    508      * @param defaultValue     The default value.
    509      * @return      The value.
    510      */
    511     public int optInt(int index, int defaultValue) {
    512         try {
    513             return getInt(index);
    514         } catch (Exception e) {
    515             return defaultValue;
    516         }
    517     }
    518 
    519 
    520     /**
    521      * Get the optional JSONArray associated with an index.
    522      * @param index subscript
    523      * @return      A JSONArray value, or null if the index has no value,
    524      * or if the value is not a JSONArray.
    525      */
    526     public JSONArray optJSONArray(int index) {
    527         Object o = opt(index);
    528         return o instanceof JSONArray ? (JSONArray)o : null;
    529     }
    530 
    531 
    532     /**
    533      * Get the optional JSONObject associated with an index.
    534      * Null is returned if the key is not found, or null if the index has
    535      * no value, or if the value is not a JSONObject.
    536      *
    537      * @param index The index must be between 0 and length() - 1.
    538      * @return      A JSONObject value.
    539      */
    540     public JSONObject optJSONObject(int index) {
    541         Object o = opt(index);
    542         return o instanceof JSONObject ? (JSONObject)o : null;
    543     }
    544 
    545 
    546     /**
    547      * Get the optional long value associated with an index.
    548      * Zero is returned if there is no value for the index,
    549      * or if the value is not a number and cannot be converted to a number.
    550      *
    551      * @param index The index must be between 0 and length() - 1.
    552      * @return      The value.
    553      */
    554     public long optLong(int index) {
    555         return optLong(index, 0);
    556     }
    557 
    558 
    559     /**
    560      * Get the optional long value associated with an index.
    561      * The defaultValue is returned if there is no value for the index,
    562      * or if the value is not a number and cannot be converted to a number.
    563      * @param index The index must be between 0 and length() - 1.
    564      * @param defaultValue     The default value.
    565      * @return      The value.
    566      */
    567     public long optLong(int index, long defaultValue) {
    568         try {
    569             return getLong(index);
    570         } catch (Exception e) {
    571             return defaultValue;
    572         }
    573     }
    574 
    575 
    576     /**
    577      * Get the optional string value associated with an index. It returns an
    578      * empty string if there is no value at that index. If the value
    579      * is not a string and is not null, then it is coverted to a string.
    580      *
    581      * @param index The index must be between 0 and length() - 1.
    582      * @return      A String value.
    583      */
    584     public String optString(int index) {
    585         return optString(index, "");
    586     }
    587 
    588 
    589     /**
    590      * Get the optional string associated with an index.
    591      * The defaultValue is returned if the key is not found.
    592      *
    593      * @param index The index must be between 0 and length() - 1.
    594      * @param defaultValue     The default value.
    595      * @return      A String value.
    596      */
    597     public String optString(int index, String defaultValue) {
    598         Object o = opt(index);
    599         return o != null ? o.toString() : defaultValue;
    600     }
    601 
    602 
    603     /**
    604      * Append a boolean value. This increases the array's length by one.
    605      *
    606      * @param value A boolean value.
    607      * @return this.
    608      */
    609     public JSONArray put(boolean value) {
    610         put(value ? Boolean.TRUE : Boolean.FALSE);
    611         return this;
    612     }
    613 
    614 
    615     /**
    616      * Put a value in the JSONArray, where the value will be a
    617      * JSONArray which is produced from a Collection.
    618      * @param value A Collection value.
    619      * @return      this.
    620      */
    621     public JSONArray put(Collection value) {
    622         put(new JSONArray(value));
    623         return this;
    624     }
    625 
    626 
    627     /**
    628      * Append a double value. This increases the array's length by one.
    629      *
    630      * @param value A double value.
    631      * @throws JSONException if the value is not finite.
    632      * @return this.
    633      */
    634     public JSONArray put(double value) throws JSONException {
    635         Double d = new Double(value);
    636         JSONObject.testValidity(d);
    637         put(d);
    638         return this;
    639     }
    640 
    641 
    642     /**
    643      * Append an int value. This increases the array's length by one.
    644      *
    645      * @param value An int value.
    646      * @return this.
    647      */
    648     public JSONArray put(int value) {
    649         put(new Integer(value));
    650         return this;
    651     }
    652 
    653 
    654     /**
    655      * Append an long value. This increases the array's length by one.
    656      *
    657      * @param value A long value.
    658      * @return this.
    659      */
    660     public JSONArray put(long value) {
    661         put(new Long(value));
    662         return this;
    663     }
    664 
    665 
    666     /**
    667      * Put a value in the JSONArray, where the value will be a
    668      * JSONObject which is produced from a Map.
    669      * @param value A Map value.
    670      * @return      this.
    671      */
    672     public JSONArray put(Map value) {
    673         put(new JSONObject(value));
    674         return this;
    675     }
    676 
    677 
    678     /**
    679      * Append an object value. This increases the array's length by one.
    680      * @param value An object value.  The value should be a
    681      *  Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the
    682      *  JSONObject.NULL object.
    683      * @return this.
    684      */
    685     public JSONArray put(Object value) {
    686         this.myArrayList.add(value);
    687         return this;
    688     }
    689 
    690 
    691     /**
    692      * Put or replace a boolean value in the JSONArray. If the index is greater
    693      * than the length of the JSONArray, then null elements will be added as
    694      * necessary to pad it out.
    695      * @param index The subscript.
    696      * @param value A boolean value.
    697      * @return this.
    698      * @throws JSONException If the index is negative.
    699      */
    700     public JSONArray put(int index, boolean value) throws JSONException {
    701         put(index, value ? Boolean.TRUE : Boolean.FALSE);
    702         return this;
    703     }
    704 
    705 
    706     /**
    707      * Put a value in the JSONArray, where the value will be a
    708      * JSONArray which is produced from a Collection.
    709      * @param index The subscript.
    710      * @param value A Collection value.
    711      * @return      this.
    712      * @throws JSONException If the index is negative or if the value is
    713      * not finite.
    714      */
    715     public JSONArray put(int index, Collection value) throws JSONException {
    716         put(index, new JSONArray(value));
    717         return this;
    718     }
    719 
    720 
    721     /**
    722      * Put or replace a double value. If the index is greater than the length of
    723      *  the JSONArray, then null elements will be added as necessary to pad
    724      *  it out.
    725      * @param index The subscript.
    726      * @param value A double value.
    727      * @return this.
    728      * @throws JSONException If the index is negative or if the value is
    729      * not finite.
    730      */
    731     public JSONArray put(int index, double value) throws JSONException {
    732         put(index, new Double(value));
    733         return this;
    734     }
    735 
    736 
    737     /**
    738      * Put or replace an int value. If the index is greater than the length of
    739      *  the JSONArray, then null elements will be added as necessary to pad
    740      *  it out.
    741      * @param index The subscript.
    742      * @param value An int value.
    743      * @return this.
    744      * @throws JSONException If the index is negative.
    745      */
    746     public JSONArray put(int index, int value) throws JSONException {
    747         put(index, new Integer(value));
    748         return this;
    749     }
    750 
    751 
    752     /**
    753      * Put or replace a long value. If the index is greater than the length of
    754      *  the JSONArray, then null elements will be added as necessary to pad
    755      *  it out.
    756      * @param index The subscript.
    757      * @param value A long value.
    758      * @return this.
    759      * @throws JSONException If the index is negative.
    760      */
    761     public JSONArray put(int index, long value) throws JSONException {
    762         put(index, new Long(value));
    763         return this;
    764     }
    765 
    766 
    767     /**
    768      * Put a value in the JSONArray, where the value will be a
    769      * JSONObject which is produced from a Map.
    770      * @param index The subscript.
    771      * @param value The Map value.
    772      * @return      this.
    773      * @throws JSONException If the index is negative or if the the value is
    774      *  an invalid number.
    775      */
    776     public JSONArray put(int index, Map value) throws JSONException {
    777         put(index, new JSONObject(value));
    778         return this;
    779     }
    780 
    781 
    782     /**
    783      * Put or replace an object value in the JSONArray. If the index is greater
    784      *  than the length of the JSONArray, then null elements will be added as
    785      *  necessary to pad it out.
    786      * @param index The subscript.
    787      * @param value The value to put into the array. The value should be a
    788      *  Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the
    789      *  JSONObject.NULL object.
    790      * @return this.
    791      * @throws JSONException If the index is negative or if the the value is
    792      *  an invalid number.
    793      */
    794     public JSONArray put(int index, Object value) throws JSONException {
    795         JSONObject.testValidity(value);
    796         if (index < 0) {
    797             throw new JSONException("JSONArray[" + index + "] not found.");
    798         }
    799         if (index < length()) {
    800             this.myArrayList.set(index, value);
    801         } else {
    802             while (index != length()) {
    803                 put(JSONObject.NULL);
    804             }
    805             put(value);
    806         }
    807         return this;
    808     }
    809 
    810 
    811     /**
    812      * Remove a index and close the hole.
    813      * @param index The index of the element to be removed.
    814      * @return The value that was associated with the index,
    815      * or null if there was no value.
    816      */
    817     public Object remove(int index) {
    818     	Object o = opt(index);
    819         this.myArrayList.remove(index);
    820         return o;
    821     }
    822 
    823 
    824     /**
    825      * Produce a JSONObject by combining a JSONArray of names with the values
    826      * of this JSONArray.
    827      * @param names A JSONArray containing a list of key strings. These will be
    828      * paired with the values.
    829      * @return A JSONObject, or null if there are no names or if this JSONArray
    830      * has no values.
    831      * @throws JSONException If any of the names are null.
    832      */
    833     public JSONObject toJSONObject(JSONArray names) throws JSONException {
    834         if (names == null || names.length() == 0 || length() == 0) {
    835             return null;
    836         }
    837         JSONObject jo = new JSONObject();
    838         for (int i = 0; i < names.length(); i += 1) {
    839             jo.put(names.getString(i), this.opt(i));
    840         }
    841         return jo;
    842     }
    843 
    844 
    845     /**
    846      * Make a JSON text of this JSONArray. For compactness, no
    847      * unnecessary whitespace is added. If it is not possible to produce a
    848      * syntactically correct JSON text then null will be returned instead. This
    849      * could occur if the array contains an invalid number.
    850      * <p>
    851      * Warning: This method assumes that the data structure is acyclical.
    852      *
    853      * @return a printable, displayable, transmittable
    854      *  representation of the array.
    855      */
    856     public String toString() {
    857         try {
    858             return '[' + join(",") + ']';
    859         } catch (Exception e) {
    860             return null;
    861         }
    862     }
    863 
    864 
    865     /**
    866      * Make a prettyprinted JSON text of this JSONArray.
    867      * Warning: This method assumes that the data structure is acyclical.
    868      * @param indentFactor The number of spaces to add to each level of
    869      *  indentation.
    870      * @return a printable, displayable, transmittable
    871      *  representation of the object, beginning
    872      *  with <code>[</code>&nbsp;<small>(left bracket)</small> and ending
    873      *  with <code>]</code>&nbsp;<small>(right bracket)</small>.
    874      * @throws JSONException
    875      */
    876     public String toString(int indentFactor) throws JSONException {
    877         return toString(indentFactor, 0);
    878     }
    879 
    880 
    881     /**
    882      * Make a prettyprinted JSON text of this JSONArray.
    883      * Warning: This method assumes that the data structure is acyclical.
    884      * @param indentFactor The number of spaces to add to each level of
    885      *  indentation.
    886      * @param indent The indention of the top level.
    887      * @return a printable, displayable, transmittable
    888      *  representation of the array.
    889      * @throws JSONException
    890      */
    891     String toString(int indentFactor, int indent) throws JSONException {
    892         int len = length();
    893         if (len == 0) {
    894             return "[]";
    895         }
    896         int i;
    897         StringBuffer sb = new StringBuffer("[");
    898         if (len == 1) {
    899             sb.append(JSONObject.valueToString(this.myArrayList.get(0),
    900                     indentFactor, indent));
    901         } else {
    902             int newindent = indent + indentFactor;
    903             sb.append('\n');
    904             for (i = 0; i < len; i += 1) {
    905                 if (i > 0) {
    906                     sb.append(",\n");
    907                 }
    908                 for (int j = 0; j < newindent; j += 1) {
    909                     sb.append(' ');
    910                 }
    911                 sb.append(JSONObject.valueToString(this.myArrayList.get(i),
    912                         indentFactor, newindent));
    913             }
    914             sb.append('\n');
    915             for (i = 0; i < indent; i += 1) {
    916                 sb.append(' ');
    917             }
    918         }
    919         sb.append(']');
    920         return sb.toString();
    921     }
    922 
    923 
    924     /**
    925      * Write the contents of the JSONArray as JSON text to a writer.
    926      * For compactness, no whitespace is added.
    927      * <p>
    928      * Warning: This method assumes that the data structure is acyclical.
    929      *
    930      * @return The writer.
    931      * @throws JSONException
    932      */
    933     public Writer write(Writer writer) throws JSONException {
    934         try {
    935             boolean b = false;
    936             int     len = length();
    937 
    938             writer.write('[');
    939 
    940             for (int i = 0; i < len; i += 1) {
    941                 if (b) {
    942                     writer.write(',');
    943                 }
    944                 Object v = this.myArrayList.get(i);
    945                 if (v instanceof JSONObject) {
    946                     ((JSONObject)v).write(writer);
    947                 } else if (v instanceof JSONArray) {
    948                     ((JSONArray)v).write(writer);
    949                 } else {
    950                     writer.write(JSONObject.valueToString(v));
    951                 }
    952                 b = true;
    953             }
    954             writer.write(']');
    955             return writer;
    956         } catch (IOException e) {
    957            throw new JSONException(e);
    958         }
    959     }
    960 }