1package org.json;
2
3/*
4Copyright (c) 2002 JSON.org
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16The Software shall be used for Good, not Evil.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24SOFTWARE.
25*/
26
27import java.util.HashMap;
28import java.util.Iterator;
29import java.util.Map;
30
31// BEGIN android-note
32//   - fixed bad htm in javadoc comments -joeo
33// END android-note
34
35/**
36 * A JSONObject is an unordered collection of name/value pairs. Its
37 * external form is a string wrapped in curly braces with colons between the
38 * names and values, and commas between the values and names. The internal form
39 * is an object having <code>get</code> and <code>opt</code> methods for
40 * accessing the values by name, and <code>put</code> methods for adding or
41 * replacing values by name. The values can be any of these types:
42 * <code>Boolean</code>, <code>JSONArray</code>, <code>JSONObject</code>,
43 * <code>Number</code>, <code>String</code>, or the <code>JSONObject.NULL</code>
44 * object. A JSONObject constructor can be used to convert an external form
45 * JSON text into an internal form whose values can be retrieved with the
46 * <code>get</code> and <code>opt</code> methods, or to convert values into a
47 * JSON text using the <code>put</code> and <code>toString</code> methods.
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 * coersion for you.
57 * <p>
58 * The <code>put</code> methods adds values to an object. For example, <pre>
59 *     myString = new JSONObject().put("JSON", "Hello, World!").toString();</pre>
60 * produces the string <code>{"JSON": "Hello, World"}</code>.
61 * <p>
62 * The texts produced by the <code>toString</code> methods strictly conform to
63 * the JSON sysntax rules.
64 * The constructors are more forgiving in the texts they will accept:
65 * <ul>
66 * <li>An extra <code>,</code>&nbsp;<small>(comma)</small> may appear just
67 *     before the closing brace.</li>
68 * <li>Strings may be quoted with <code>'</code>&nbsp;<small>(single
69 *     quote)</small>.</li>
70 * <li>Strings do not need to be quoted at all if they do not begin with a quote
71 *     or single quote, and if they do not contain leading or trailing spaces,
72 *     and if they do not contain any of these characters:
73 *     <code>{ } [ ] / \ : , = ; #</code> and if they do not look like numbers
74 *     and if they are not the reserved words <code>true</code>,
75 *     <code>false</code>, or <code>null</code>.</li>
76 * <li>Keys can be followed by <code>=</code> or <code>=></code> as well as
77 *     by <code>:</code>.</li>
78 * <li>Values can be followed by <code>;</code> <small>(semicolon)</small> as
79 *     well as by <code>,</code> <small>(comma)</small>.</li>
80 * <li>Numbers may have the <code>0-</code> <small>(octal)</small> or
81 *     <code>0x-</code> <small>(hex)</small> prefix.</li>
82 * <li>Comments written in the slashshlash, slashstar, and hash conventions
83 *     will be ignored.</li>
84 * </ul>
85 * @author JSON.org
86 * @version 2
87 */
88public class JSONObject {
89
90    /**
91     * JSONObject.NULL is equivalent to the value that JavaScript calls null,
92     * whilst Java's null is equivalent to the value that JavaScript calls
93     * undefined.
94     */
95     private static final class Null {
96
97        /**
98         * There is only intended to be a single instance of the NULL object,
99         * so the clone method returns itself.
100         * @return     NULL.
101         */
102        protected final Object clone() {
103            return this;
104        }
105
106
107        /**
108         * A Null object is equal to the null value and to itself.
109         * @param object    An object to test for nullness.
110         * @return true if the object parameter is the JSONObject.NULL object
111         *  or null.
112         */
113        public boolean equals(Object object) {
114            return object == null || object == this;
115        }
116
117
118        /**
119         * Get the "null" string value.
120         * @return The string "null".
121         */
122        public String toString() {
123            return "null";
124        }
125    }
126
127
128    /**
129     * The hash map where the JSONObject's properties are kept.
130     */
131    private HashMap myHashMap;
132
133
134    /**
135     * It is sometimes more convenient and less ambiguous to have a
136     * <code>NULL</code> object than to use Java's <code>null</code> value.
137     * <code>JSONObject.NULL.equals(null)</code> returns <code>true</code>.
138     * <code>JSONObject.NULL.toString()</code> returns <code>"null"</code>.
139     */
140    public static final Object NULL = new Null();
141
142
143    /**
144     * Construct an empty JSONObject.
145     */
146    public JSONObject() {
147        this.myHashMap = new HashMap();
148    }
149
150
151    /**
152     * Construct a JSONObject from a subset of another JSONObject.
153     * An array of strings is used to identify the keys that should be copied.
154     * Missing keys are ignored.
155     * @param jo A JSONObject.
156     * @param sa An array of strings.
157     * @exception JSONException If a value is a non-finite number.
158     */
159    public JSONObject(JSONObject jo, String[] sa) throws JSONException {
160        this();
161        for (int i = 0; i < sa.length; i += 1) {
162            putOpt(sa[i], jo.opt(sa[i]));
163        }
164    }
165
166
167    /**
168     * Construct a JSONObject from a JSONTokener.
169     * @param x A JSONTokener object containing the source string.
170     * @throws JSONException If there is a syntax error in the source string.
171     */
172    public JSONObject(JSONTokener x) throws JSONException {
173        this();
174        char c;
175        String key;
176
177        if (x.nextClean() != '{') {
178            throw x.syntaxError("A JSONObject text must begin with '{'");
179        }
180        for (;;) {
181            c = x.nextClean();
182            switch (c) {
183            case 0:
184                throw x.syntaxError("A JSONObject text must end with '}'");
185            case '}':
186                return;
187            default:
188                x.back();
189                key = x.nextValue().toString();
190            }
191
192            /*
193             * The key is followed by ':'. We will also tolerate '=' or '=>'.
194             */
195
196            c = x.nextClean();
197            if (c == '=') {
198                if (x.next() != '>') {
199                    x.back();
200                }
201            } else if (c != ':') {
202                throw x.syntaxError("Expected a ':' after a key");
203            }
204            this.myHashMap.put(key, x.nextValue());
205
206            /*
207             * Pairs are separated by ','. We will also tolerate ';'.
208             */
209
210            switch (x.nextClean()) {
211            case ';':
212            case ',':
213                if (x.nextClean() == '}') {
214                    return;
215                }
216                x.back();
217                break;
218            case '}':
219                return;
220            default:
221                throw x.syntaxError("Expected a ',' or '}'");
222            }
223        }
224    }
225
226
227    /**
228     * Construct a JSONObject from a Map.
229     * @param map A map object that can be used to initialize the contents of
230     *  the JSONObject.
231     */
232    public JSONObject(Map map) {
233        this.myHashMap = new HashMap(map);
234    }
235
236
237    /**
238     * Construct a JSONObject from a string.
239     * This is the most commonly used JSONObject constructor.
240     * @param string    A string beginning
241     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
242     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
243     * @exception JSONException If there is a syntax error in the source string.
244     */
245    public JSONObject(String string) throws JSONException {
246        this(new JSONTokener(string));
247    }
248
249
250    /**
251     * Accumulate values under a key. It is similar to the put method except
252     * that if there is already an object stored under the key then a
253     * JSONArray is stored under the key to hold all of the accumulated values.
254     * If there is already a JSONArray, then the new value is appended to it.
255     * In contrast, the put method replaces the previous value.
256     * @param key   A key string.
257     * @param value An object to be accumulated under the key.
258     * @return this.
259     * @throws JSONException If the value is an invalid number
260     *  or if the key is null.
261     */
262    public JSONObject accumulate(String key, Object value)
263            throws JSONException {
264        testValidity(value);
265        Object o = opt(key);
266        if (o == null) {
267            put(key, value);
268        } else if (o instanceof JSONArray) {
269            ((JSONArray)o).put(value);
270        } else {
271            put(key, new JSONArray().put(o).put(value));
272        }
273        return this;
274    }
275
276
277    /**
278     * Get the value object associated with a key.
279     *
280     * @param key   A key string.
281     * @return      The object associated with the key.
282     * @throws   JSONException if the key is not found.
283     */
284    public Object get(String key) throws JSONException {
285        Object o = opt(key);
286        if (o == null) {
287            throw new JSONException("JSONObject[" + quote(key) +
288                    "] not found.");
289        }
290        return o;
291    }
292
293
294    /**
295     * Get the boolean value associated with a key.
296     *
297     * @param key   A key string.
298     * @return      The truth.
299     * @throws   JSONException
300     *  if the value is not a Boolean or the String "true" or "false".
301     */
302    public boolean getBoolean(String key) throws JSONException {
303        Object o = get(key);
304        if (o.equals(Boolean.FALSE) ||
305                (o instanceof String &&
306                ((String)o).equalsIgnoreCase("false"))) {
307            return false;
308        } else if (o.equals(Boolean.TRUE) ||
309                (o instanceof String &&
310                ((String)o).equalsIgnoreCase("true"))) {
311            return true;
312        }
313        throw new JSONException("JSONObject[" + quote(key) +
314                "] is not a Boolean.");
315    }
316
317
318    /**
319     * Get the double value associated with a key.
320     * @param key   A key string.
321     * @return      The numeric value.
322     * @throws JSONException if the key is not found or
323     *  if the value is not a Number object and cannot be converted to a number.
324     */
325    public double getDouble(String key) throws JSONException {
326        Object o = get(key);
327        try {
328            return o instanceof Number ?
329                    ((Number)o).doubleValue() : Double.parseDouble((String)o);
330        } catch (Exception e) {
331            throw new JSONException("JSONObject[" + quote(key) +
332                "] is not a number.");
333        }
334    }
335
336
337    /**
338     * Get the int value associated with a key. If the number value is too
339     * large for an int, it will be clipped.
340     *
341     * @param key   A key string.
342     * @return      The integer value.
343     * @throws   JSONException if the key is not found or if the value cannot
344     *     be converted to an integer.
345     */
346    public int getInt(String key) throws JSONException {
347        Object o = get(key);
348        return o instanceof Number ?
349                ((Number)o).intValue() : (int)getDouble(key);
350    }
351
352
353    /**
354     * Get the JSONArray value associated with a key.
355     *
356     * @param key   A key string.
357     * @return      A JSONArray which is the value.
358     * @throws   JSONException if the key is not found or
359     *  if the value is not a JSONArray.
360     */
361    public JSONArray getJSONArray(String key) throws JSONException {
362        Object o = get(key);
363        if (o instanceof JSONArray) {
364            return (JSONArray)o;
365        }
366        throw new JSONException("JSONObject[" + quote(key) +
367                "] is not a JSONArray.");
368    }
369
370
371    /**
372     * Get the JSONObject value associated with a key.
373     *
374     * @param key   A key string.
375     * @return      A JSONObject which is the value.
376     * @throws   JSONException if the key is not found or
377     *  if the value is not a JSONObject.
378     */
379    public JSONObject getJSONObject(String key) throws JSONException {
380        Object o = get(key);
381        if (o instanceof JSONObject) {
382            return (JSONObject)o;
383        }
384        throw new JSONException("JSONObject[" + quote(key) +
385                "] is not a JSONObject.");
386    }
387
388
389    /**
390     * Get the long value associated with a key. If the number value is too
391     * long for a long, it will be clipped.
392     *
393     * @param key   A key string.
394     * @return      The long value.
395     * @throws   JSONException if the key is not found or if the value cannot
396     *     be converted to a long.
397     */
398    public long getLong(String key) throws JSONException {
399        Object o = get(key);
400        return o instanceof Number ?
401                ((Number)o).longValue() : (long)getDouble(key);
402    }
403
404
405    /**
406     * Get the string associated with a key.
407     *
408     * @param key   A key string.
409     * @return      A string which is the value.
410     * @throws   JSONException if the key is not found.
411     */
412    public String getString(String key) throws JSONException {
413        return get(key).toString();
414    }
415
416
417    /**
418     * Determine if the JSONObject contains a specific key.
419     * @param key   A key string.
420     * @return      true if the key exists in the JSONObject.
421     */
422    public boolean has(String key) {
423        return this.myHashMap.containsKey(key);
424    }
425
426
427    /**
428     * Determine if the value associated with the key is null or if there is
429     *  no value.
430     * @param key   A key string.
431     * @return      true if there is no value associated with the key or if
432     *  the value is the JSONObject.NULL object.
433     */
434    public boolean isNull(String key) {
435        return JSONObject.NULL.equals(opt(key));
436    }
437
438
439    /**
440     * Get an enumeration of the keys of the JSONObject.
441     *
442     * @return An iterator of the keys.
443     */
444    public Iterator keys() {
445        return this.myHashMap.keySet().iterator();
446    }
447
448
449    /**
450     * Get the number of keys stored in the JSONObject.
451     *
452     * @return The number of keys in the JSONObject.
453     */
454    public int length() {
455        return this.myHashMap.size();
456    }
457
458
459    /**
460     * Produce a JSONArray containing the names of the elements of this
461     * JSONObject.
462     * @return A JSONArray containing the key strings, or null if the JSONObject
463     * is empty.
464     */
465    public JSONArray names() {
466        JSONArray ja = new JSONArray();
467        Iterator  keys = keys();
468        while (keys.hasNext()) {
469            ja.put(keys.next());
470        }
471        return ja.length() == 0 ? null : ja;
472    }
473
474    /**
475     * Produce a string from a number.
476     * @param  n A Number
477     * @return A String.
478     * @throws JSONException If n is a non-finite number.
479     */
480    static public String numberToString(Number n)
481            throws JSONException {
482        if (n == null) {
483            throw new JSONException("Null pointer");
484        }
485        testValidity(n);
486
487// Shave off trailing zeros and decimal point, if possible.
488
489        String s = n.toString();
490        if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) {
491            while (s.endsWith("0")) {
492                s = s.substring(0, s.length() - 1);
493            }
494            if (s.endsWith(".")) {
495                s = s.substring(0, s.length() - 1);
496            }
497        }
498        return s;
499    }
500
501
502    /**
503     * Get an optional value associated with a key.
504     * @param key   A key string.
505     * @return      An object which is the value, or null if there is no value.
506     */
507    public Object opt(String key) {
508        return key == null ? null : this.myHashMap.get(key);
509    }
510
511
512    /**
513     * Get an optional boolean associated with a key.
514     * It returns false if there is no such key, or if the value is not
515     * Boolean.TRUE or the String "true".
516     *
517     * @param key   A key string.
518     * @return      The truth.
519     */
520    public boolean optBoolean(String key) {
521        return optBoolean(key, false);
522    }
523
524
525    /**
526     * Get an optional boolean associated with a key.
527     * It returns the defaultValue if there is no such key, or if it is not
528     * a Boolean or the String "true" or "false" (case insensitive).
529     *
530     * @param key              A key string.
531     * @param defaultValue     The default.
532     * @return      The truth.
533     */
534    public boolean optBoolean(String key, boolean defaultValue) {
535        try {
536            return getBoolean(key);
537        } catch (Exception e) {
538            return defaultValue;
539        }
540    }
541
542
543    /**
544     * Get an optional double associated with a key,
545     * or NaN if there is no such key or if its value is not a number.
546     * If the value is a string, an attempt will be made to evaluate it as
547     * a number.
548     *
549     * @param key   A string which is the key.
550     * @return      An object which is the value.
551     */
552    public double optDouble(String key) {
553        return optDouble(key, Double.NaN);
554    }
555
556
557    /**
558     * Get an optional double associated with a key, or the
559     * defaultValue if there is no such key or if its value is not a number.
560     * If the value is a string, an attempt will be made to evaluate it as
561     * a number.
562     *
563     * @param key   A key string.
564     * @param defaultValue     The default.
565     * @return      An object which is the value.
566     */
567    public double optDouble(String key, double defaultValue) {
568        try {
569            Object o = opt(key);
570            return o instanceof Number ? ((Number)o).doubleValue() :
571                new Double((String)o).doubleValue();
572        } catch (Exception e) {
573            return defaultValue;
574        }
575    }
576
577
578    /**
579     * Get an optional int value associated with a key,
580     * or zero if there is no such key or if the value is not a number.
581     * If the value is a string, an attempt will be made to evaluate it as
582     * a number.
583     *
584     * @param key   A key string.
585     * @return      An object which is the value.
586     */
587    public int optInt(String key) {
588        return optInt(key, 0);
589    }
590
591
592    /**
593     * Get an optional int value associated with a key,
594     * or the default if there is no such key or if the value is not a number.
595     * If the value is a string, an attempt will be made to evaluate it as
596     * a number.
597     *
598     * @param key   A key string.
599     * @param defaultValue     The default.
600     * @return      An object which is the value.
601     */
602    public int optInt(String key, int defaultValue) {
603        try {
604            return getInt(key);
605        } catch (Exception e) {
606            return defaultValue;
607        }
608    }
609
610
611    /**
612     * Get an optional JSONArray associated with a key.
613     * It returns null if there is no such key, or if its value is not a
614     * JSONArray.
615     *
616     * @param key   A key string.
617     * @return      A JSONArray which is the value.
618     */
619    public JSONArray optJSONArray(String key) {
620        Object o = opt(key);
621        return o instanceof JSONArray ? (JSONArray)o : null;
622    }
623
624
625    /**
626     * Get an optional JSONObject associated with a key.
627     * It returns null if there is no such key, or if its value is not a
628     * JSONObject.
629     *
630     * @param key   A key string.
631     * @return      A JSONObject which is the value.
632     */
633    public JSONObject optJSONObject(String key) {
634        Object o = opt(key);
635        return o instanceof JSONObject ? (JSONObject)o : null;
636    }
637
638
639    /**
640     * Get an optional long value associated with a key,
641     * or zero if there is no such key or if the value is not a number.
642     * If the value is a string, an attempt will be made to evaluate it as
643     * a number.
644     *
645     * @param key   A key string.
646     * @return      An object which is the value.
647     */
648    public long optLong(String key) {
649        return optLong(key, 0);
650    }
651
652
653    /**
654     * Get an optional long value associated with a key,
655     * or the default if there is no such key or if the value is not a number.
656     * If the value is a string, an attempt will be made to evaluate it as
657     * a number.
658     *
659     * @param key   A key string.
660     * @param defaultValue     The default.
661     * @return      An object which is the value.
662     */
663    public long optLong(String key, long defaultValue) {
664        try {
665            return getLong(key);
666        } catch (Exception e) {
667            return defaultValue;
668        }
669    }
670
671
672    /**
673     * Get an optional string associated with a key.
674     * It returns an empty string if there is no such key. If the value is not
675     * a string and is not null, then it is coverted to a string.
676     *
677     * @param key   A key string.
678     * @return      A string which is the value.
679     */
680    public String optString(String key) {
681        return optString(key, "");
682    }
683
684
685    /**
686     * Get an optional string associated with a key.
687     * It returns the defaultValue if there is no such key.
688     *
689     * @param key   A key string.
690     * @param defaultValue     The default.
691     * @return      A string which is the value.
692     */
693    public String optString(String key, String defaultValue) {
694        Object o = opt(key);
695        return o != null ? o.toString() : defaultValue;
696    }
697
698
699    /**
700     * Put a key/boolean pair in the JSONObject.
701     *
702     * @param key   A key string.
703     * @param value A boolean which is the value.
704     * @return this.
705     * @throws JSONException If the key is null.
706     */
707    public JSONObject put(String key, boolean value) throws JSONException {
708        put(key, Boolean.valueOf(value));
709        return this;
710    }
711
712
713    /**
714     * Put a key/double pair in the JSONObject.
715     *
716     * @param key   A key string.
717     * @param value A double which is the value.
718     * @return this.
719     * @throws JSONException If the key is null or if the number is invalid.
720     */
721    public JSONObject put(String key, double value) throws JSONException {
722        put(key, new Double(value));
723        return this;
724    }
725
726
727    /**
728     * Put a key/int pair in the JSONObject.
729     *
730     * @param key   A key string.
731     * @param value An int which is the value.
732     * @return this.
733     * @throws JSONException If the key is null.
734     */
735    public JSONObject put(String key, int value) throws JSONException {
736        put(key, new Integer(value));
737        return this;
738    }
739
740
741    /**
742     * Put a key/long pair in the JSONObject.
743     *
744     * @param key   A key string.
745     * @param value A long which is the value.
746     * @return this.
747     * @throws JSONException If the key is null.
748     */
749    public JSONObject put(String key, long value) throws JSONException {
750        put(key, new Long(value));
751        return this;
752    }
753
754
755    /**
756     * Put a key/value pair in the JSONObject. If the value is null,
757     * then the key will be removed from the JSONObject if it is present.
758     * @param key   A key string.
759     * @param value An object which is the value. It should be of one of these
760     *  types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String,
761     *  or the JSONObject.NULL object.
762     * @return this.
763     * @throws JSONException If the value is non-finite number
764     *     or if the key is null.
765     */
766    public JSONObject put(String key, Object value)
767            throws JSONException {
768        if (key == null) {
769            throw new JSONException("Null key.");
770        }
771        if (value != null) {
772            testValidity(value);
773            this.myHashMap.put(key, value);
774        } else {
775            remove(key);
776        }
777        return this;
778    }
779
780
781    /**
782     * Put a key/value pair in the JSONObject, but only if the
783     * key and the value are both non-null.
784     * @param key   A key string.
785     * @param value An object which is the value. It should be of one of these
786     *  types: Boolean, Double, Integer, JSONArray, JSONObject, Long, String,
787     *  or the JSONObject.NULL object.
788     * @return this.
789     * @throws JSONException If the value is a non-finite number.
790     */
791    public JSONObject putOpt(String key, Object value) throws JSONException {
792        if (key != null && value != null) {
793            put(key, value);
794        }
795        return this;
796    }
797
798
799    /**
800     * Produce a string in double quotes with backslash sequences in all the
801     * right places. A backslash will be inserted within &lt;/, allowing JSON
802     * text to be delivered in HTML. In JSON text, a string cannot contain a
803     * control character or an unescaped quote or backslash.
804     * @param string A String
805     * @return  A String correctly formatted for insertion in a JSON text.
806     */
807    public static String quote(String string) {
808        if (string == null || string.length() == 0) {
809            return "\"\"";
810        }
811
812        char         b;
813        char         c = 0;
814        int          i;
815        int          len = string.length();
816        StringBuilder sb = new StringBuilder(len + 4);
817        String       t;
818
819        sb.append('"');
820        for (i = 0; i < len; i += 1) {
821            b = c;
822            c = string.charAt(i);
823            switch (c) {
824            case '\\':
825            case '"':
826                sb.append('\\');
827                sb.append(c);
828                break;
829            case '/':
830                if (b == '<') {
831                    sb.append('\\');
832                }
833                sb.append(c);
834                break;
835            case '\b':
836                sb.append("\\b");
837                break;
838            case '\t':
839                sb.append("\\t");
840                break;
841            case '\n':
842                sb.append("\\n");
843                break;
844            case '\f':
845                sb.append("\\f");
846                break;
847            case '\r':
848                sb.append("\\r");
849                break;
850            default:
851                if (c < ' ') {
852                    t = "000" + Integer.toHexString(c);
853                    sb.append("\\u" + t.substring(t.length() - 4));
854                } else {
855                    sb.append(c);
856                }
857            }
858        }
859        sb.append('"');
860        return sb.toString();
861    }
862
863    /**
864     * Remove a name and its value, if present.
865     * @param key The name to be removed.
866     * @return The value that was associated with the name,
867     * or null if there was no value.
868     */
869    public Object remove(String key) {
870        return this.myHashMap.remove(key);
871    }
872
873    /**
874     * Throw an exception if the object is an NaN or infinite number.
875     * @param o The object to test.
876     * @throws JSONException If o is a non-finite number.
877     */
878    static void testValidity(Object o) throws JSONException {
879        if (o != null) {
880            if (o instanceof Double) {
881                if (((Double)o).isInfinite() || ((Double)o).isNaN()) {
882                    throw new JSONException(
883                        "JSON does not allow non-finite numbers");
884                }
885            } else if (o instanceof Float) {
886                if (((Float)o).isInfinite() || ((Float)o).isNaN()) {
887                    throw new JSONException(
888                        "JSON does not allow non-finite numbers.");
889                }
890            }
891        }
892    }
893
894
895    /**
896     * Produce a JSONArray containing the values of the members of this
897     * JSONObject.
898     * @param names A JSONArray containing a list of key strings. This
899     * determines the sequence of the values in the result.
900     * @return A JSONArray of values.
901     * @throws JSONException If any of the values are non-finite numbers.
902     */
903    public JSONArray toJSONArray(JSONArray names) throws JSONException {
904        if (names == null || names.length() == 0) {
905            return null;
906        }
907        JSONArray ja = new JSONArray();
908        for (int i = 0; i < names.length(); i += 1) {
909            ja.put(this.opt(names.getString(i)));
910        }
911        return ja;
912    }
913
914    /**
915     * Make an JSON text of this JSONObject. For compactness, no whitespace
916     * is added. If this would not result in a syntactically correct JSON text,
917     * then null will be returned instead.
918     * <p>
919     * Warning: This method assumes that the data structure is acyclical.
920     *
921     * @return a printable, displayable, portable, transmittable
922     *  representation of the object, beginning
923     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
924     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
925     */
926    public String toString() {
927        try {
928            Iterator     keys = keys();
929            StringBuilder sb = new StringBuilder("{");
930
931            while (keys.hasNext()) {
932                if (sb.length() > 1) {
933                    sb.append(',');
934                }
935                Object o = keys.next();
936                sb.append(quote(o.toString()));
937                sb.append(':');
938                sb.append(valueToString(this.myHashMap.get(o)));
939            }
940            sb.append('}');
941            return sb.toString();
942        } catch (Exception e) {
943            return null;
944        }
945    }
946
947
948    /**
949     * Make a prettyprinted JSON text of this JSONObject.
950     * <p>
951     * Warning: This method assumes that the data structure is acyclical.
952     * @param indentFactor The number of spaces to add to each level of
953     *  indentation.
954     * @return a printable, displayable, portable, transmittable
955     *  representation of the object, beginning
956     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
957     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
958     * @throws JSONException If the object contains an invalid number.
959     */
960    public String toString(int indentFactor) throws JSONException {
961        return toString(indentFactor, 0);
962    }
963
964
965    /**
966     * Make a prettyprinted JSON text of this JSONObject.
967     * <p>
968     * Warning: This method assumes that the data structure is acyclical.
969     * @param indentFactor The number of spaces to add to each level of
970     *  indentation.
971     * @param indent The indentation of the top level.
972     * @return a printable, displayable, transmittable
973     *  representation of the object, beginning
974     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
975     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
976     * @throws JSONException If the object contains an invalid number.
977     */
978    String toString(int indentFactor, int indent) throws JSONException {
979        int          i;
980        int          n = length();
981        if (n == 0) {
982            return "{}";
983        }
984        Iterator     keys = keys();
985        StringBuilder sb = new StringBuilder("{");
986        int          newindent = indent + indentFactor;
987        Object       o;
988        if (n == 1) {
989            o = keys.next();
990            sb.append(quote(o.toString()));
991            sb.append(": ");
992            sb.append(valueToString(this.myHashMap.get(o), indentFactor,
993                    indent));
994        } else {
995            while (keys.hasNext()) {
996                o = keys.next();
997                if (sb.length() > 1) {
998                    sb.append(",\n");
999                } else {
1000                    sb.append('\n');
1001                }
1002                for (i = 0; i < newindent; i += 1) {
1003                    sb.append(' ');
1004                }
1005                sb.append(quote(o.toString()));
1006                sb.append(": ");
1007                sb.append(valueToString(this.myHashMap.get(o), indentFactor,
1008                        newindent));
1009            }
1010            if (sb.length() > 1) {
1011                sb.append('\n');
1012                for (i = 0; i < indent; i += 1) {
1013                    sb.append(' ');
1014                }
1015            }
1016        }
1017        sb.append('}');
1018        return sb.toString();
1019    }
1020
1021
1022    /**
1023     * Make a JSON text of an object value.
1024     * <p>
1025     * Warning: This method assumes that the data structure is acyclical.
1026     * @param value The value to be serialized.
1027     * @return a printable, displayable, transmittable
1028     *  representation of the object, beginning
1029     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
1030     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
1031     * @throws JSONException If the value is or contains an invalid number.
1032     */
1033    static String valueToString(Object value) throws JSONException {
1034        if (value == null || value.equals(null)) {
1035            return "null";
1036        }
1037        if (value instanceof Number) {
1038            return numberToString((Number) value);
1039        }
1040        if (value instanceof Boolean || value instanceof JSONObject ||
1041                value instanceof JSONArray) {
1042            return value.toString();
1043        }
1044        return quote(value.toString());
1045    }
1046
1047
1048    /**
1049     * Make a prettyprinted JSON text of an object value.
1050     * <p>
1051     * Warning: This method assumes that the data structure is acyclical.
1052     * @param value The value to be serialized.
1053     * @param indentFactor The number of spaces to add to each level of
1054     *  indentation.
1055     * @param indent The indentation of the top level.
1056     * @return a printable, displayable, transmittable
1057     *  representation of the object, beginning
1058     *  with <code>{</code>&nbsp;<small>(left brace)</small> and ending
1059     *  with <code>}</code>&nbsp;<small>(right brace)</small>.
1060     * @throws JSONException If the object contains an invalid number.
1061     */
1062     static String valueToString(Object value, int indentFactor, int indent)
1063             throws JSONException {
1064        if (value == null || value.equals(null)) {
1065            return "null";
1066        }
1067        if (value instanceof Number) {
1068            return numberToString((Number) value);
1069        }
1070        if (value instanceof Boolean) {
1071            return value.toString();
1072        }
1073        if (value instanceof JSONObject) {
1074            return ((JSONObject)value).toString(indentFactor, indent);
1075        }
1076        if (value instanceof JSONArray) {
1077            return ((JSONArray)value).toString(indentFactor, indent);
1078        }
1079        return quote(value.toString());
1080    }
1081}
1082