JAL-3438 spotless for 2.11.2.0
[jalview.git] / src / org / json / JSONObject.java
1 package org.json;
2
3 import java.io.Closeable;
4
5 /*
6  * 
7  * Note: This file has been adapted for SwingJS by Bob Hanson hansonr@stolaf.edu 
8  * 
9  Copyright (c) 2002 JSON.org
10
11  Permission is hereby granted, free of charge, to any person obtaining a copy
12  of this software and associated documentation files (the "Software"), to deal
13  in the Software without restriction, including without limitation the rights
14  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  copies of the Software, and to permit persons to whom the Software is
16  furnished to do so, subject to the following conditions:
17
18  The above copyright notice and this permission notice shall be included in all
19  copies or substantial portions of the Software.
20
21  The Software shall be used for Good, not Evil.
22
23  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  SOFTWARE.
30  */
31
32 import java.io.IOException;
33 import java.io.StringWriter;
34 import java.io.Writer;
35 import java.lang.annotation.Annotation;
36 import java.lang.reflect.Field;
37 import java.lang.reflect.InvocationTargetException;
38 import java.lang.reflect.Method;
39 import java.lang.reflect.Modifier;
40 import java.math.BigDecimal;
41 import java.math.BigInteger;
42 import java.util.Collection;
43 import java.util.Enumeration;
44 import java.util.HashMap;
45 import java.util.Iterator;
46 import java.util.Locale;
47 import java.util.Map;
48 import java.util.Map.Entry;
49 import java.util.ResourceBundle;
50 import java.util.Set;
51
52 /**
53  * A JSONObject is an unordered collection of name/value pairs. Its external
54  * form is a string wrapped in curly braces with colons between the names and
55  * values, and commas between the values and names. The internal form is an
56  * object having <code>get</code> and <code>opt</code> methods for accessing the
57  * values by name, and <code>put</code> methods for adding or replacing values
58  * by name. The values can be any of these types: <code>Boolean</code>,
59  * <code>JSONArray</code>, <code>JSONObject</code>, <code>Number</code>,
60  * <code>String</code>, or the <code>JSONObject.NULL</code> object. A JSONObject
61  * constructor can be used to convert an external form JSON text into an
62  * internal form whose values can be retrieved with the <code>get</code> and
63  * <code>opt</code> methods, or to convert values into a JSON text using the
64  * <code>put</code> and <code>toString</code> methods. A <code>get</code> method
65  * returns a value if one can be found, and throws an exception if one cannot be
66  * found. An <code>opt</code> method returns a default value instead of throwing
67  * an exception, and so is useful for obtaining optional values.
68  * <p>
69  * The generic <code>get()</code> and <code>opt()</code> methods return an
70  * object, which you can cast or query for type. There are also typed
71  * <code>get</code> and <code>opt</code> methods that do type checking and type
72  * coercion for you. The opt methods differ from the get methods in that they do
73  * not throw. Instead, they return a specified value, such as null.
74  * <p>
75  * The <code>put</code> methods add or replace values in an object. For example,
76  *
77  * <pre>
78  * myString = new JSONObject().put(&quot;JSON&quot;, &quot;Hello, World!&quot;).toString();
79  * </pre>
80  *
81  * produces the string <code>{"JSON": "Hello, World"}</code>.
82  * <p>
83  * The texts produced by the <code>toString</code> methods strictly conform to
84  * the JSON syntax rules. The constructors are more forgiving in the texts they
85  * will accept:
86  * <ul>
87  * <li>An extra <code>,</code>&nbsp;<small>(comma)</small> may appear just
88  * before the closing brace.</li>
89  * <li>Strings may be quoted with <code>'</code>&nbsp;<small>(single
90  * quote)</small>.</li>
91  * <li>Strings do not need to be quoted at all if they do not begin with a quote
92  * or single quote, and if they do not contain leading or trailing spaces, and
93  * if they do not contain any of these characters:
94  * <code>{ } [ ] / \ : , #</code> and if they do not look like numbers and if
95  * they are not the reserved words <code>true</code>, <code>false</code>, or
96  * <code>null</code>.</li>
97  * </ul>
98  *
99  * @author JSON.org
100  * @version 2016-08-15
101  */
102 public class JSONObject
103 {
104   /**
105    * JSONObject.NULL is equivalent to the value that JavaScript calls null,
106    * whilst Java's null is equivalent to the value that JavaScript calls
107    * undefined.
108    */
109   private static final class Null
110   {
111
112     /**
113      * There is only intended to be a single instance of the NULL object, so the
114      * clone method returns itself.
115      *
116      * @return NULL.
117      */
118     @Override
119     protected final Object clone()
120     {
121       return this;
122     }
123
124     /**
125      * A Null object is equal to the null value and to itself.
126      *
127      * @param object
128      *          An object to test for nullness.
129      * @return true if the object parameter is the JSONObject.NULL object or
130      *         null.
131      */
132     @Override
133     public boolean equals(Object object)
134     {
135       return object == null || object == this;
136     }
137
138     /**
139      * A Null object is equal to the null value and to itself.
140      *
141      * @return always returns 0.
142      */
143     @Override
144     public int hashCode()
145     {
146       return 0;
147     }
148
149     /**
150      * Get the "null" string value.
151      *
152      * @return The string "null".
153      */
154     @Override
155     public String toString()
156     {
157       return "null";
158     }
159   }
160
161   /**
162    * The map where the JSONObject's properties are kept.
163    */
164   private final Map<String, Object> map;
165
166   /**
167    * It is sometimes more convenient and less ambiguous to have a
168    * <code>NULL</code> object than to use Java's <code>null</code> value.
169    * <code>JSONObject.NULL.equals(null)</code> returns <code>true</code>.
170    * <code>JSONObject.NULL.toString()</code> returns <code>"null"</code>.
171    */
172   public static final Object NULL = new Null();
173
174   /**
175    * Construct an empty JSONObject.
176    */
177   public JSONObject()
178   {
179     // HashMap is used on purpose to ensure that elements are unordered by
180     // the specification.
181     // JSON tends to be a portable transfer format to allows the container
182     // implementations to rearrange their items for a faster element
183     // retrieval based on associative access.
184     // Therefore, an implementation mustn't rely on the order of the item.
185     this.map = new HashMap<String, Object>();
186   }
187
188   /**
189    * Construct a JSONObject from a subset of another JSONObject. An array of
190    * strings is used to identify the keys that should be copied. Missing keys
191    * are ignored.
192    *
193    * @param jo
194    *          A JSONObject.
195    * @param names
196    *          An array of strings.
197    */
198   public JSONObject(JSONObject jo, String[] names)
199   {
200     this(names.length);
201     for (int i = 0; i < names.length; i += 1)
202     {
203       try
204       {
205         this.putOnce(names[i], jo.opt(names[i]));
206       } catch (Exception ignore)
207       {
208       }
209     }
210   }
211
212   /**
213    * Construct a JSONObject from a JSONTokener.
214    *
215    * @param x
216    *          A JSONTokener object containing the source string.
217    * @throws JSONException
218    *           If there is a syntax error in the source string or a duplicated
219    *           key.
220    */
221   public JSONObject(JSONTokener x) throws JSONException
222   {
223     this();
224     char c;
225     String key;
226
227     if (x.nextClean() != '{')
228     {
229       throw x.syntaxError("A JSONObject text must begin with '{'");
230     }
231     for (;;)
232     {
233       c = x.nextClean();
234       switch (c)
235       {
236       case 0:
237         throw x.syntaxError("A JSONObject text must end with '}'");
238       case '}':
239         return;
240       default:
241         x.back();
242         key = x.nextValue().toString();
243       }
244
245       // The key is followed by ':'.
246
247       c = x.nextClean();
248       if (c != ':')
249       {
250         throw x.syntaxError("Expected a ':' after a key");
251       }
252
253       // Use syntaxError(..) to include error location
254
255       if (key != null)
256       {
257         // Check if key exists
258         if (this.opt(key) != null)
259         {
260           // key already exists
261           throw x.syntaxError("Duplicate key \"" + key + "\"");
262         }
263         // Only add value if non-null
264         Object value = x.nextValue();
265         if (value != null)
266         {
267           this.put(key, value);
268         }
269       }
270
271       // Pairs are separated by ','.
272
273       switch (x.nextClean())
274       {
275       case ';':
276       case ',':
277         if (x.nextClean() == '}')
278         {
279           return;
280         }
281         x.back();
282         break;
283       case '}':
284         return;
285       default:
286         throw x.syntaxError("Expected a ',' or '}'");
287       }
288     }
289   }
290
291   /**
292    * Construct a JSONObject from a Map.
293    *
294    * @param m
295    *          A map object that can be used to initialize the contents of the
296    *          JSONObject.
297    * @throws JSONException
298    *           If a value in the map is non-finite number.
299    * @throws NullPointerException
300    *           If a key in the map is <code>null</code>
301    */
302   public JSONObject(Map<?, ?> m)
303   {
304     if (m == null)
305     {
306       this.map = new HashMap<String, Object>();
307     }
308     else
309     {
310       this.map = new HashMap<String, Object>(m.size());
311       for (final Entry<?, ?> e : m.entrySet())
312       {
313         if (e.getKey() == null)
314         {
315           throw new NullPointerException("Null key.");
316         }
317         final Object value = e.getValue();
318         if (value != null)
319         {
320           this.map.put(String.valueOf(e.getKey()), wrap(value));
321         }
322       }
323     }
324   }
325
326   /**
327    * Construct a JSONObject from an Object using bean getters. It reflects on
328    * all of the public methods of the object. For each of the methods with no
329    * parameters and a name starting with <code>"get"</code> or <code>"is"</code>
330    * followed by an uppercase letter, the method is invoked, and a key and the
331    * value returned from the getter method are put into the new JSONObject.
332    * <p>
333    * The key is formed by removing the <code>"get"</code> or <code>"is"</code>
334    * prefix. If the second remaining character is not upper case, then the first
335    * character is converted to lower case.
336    * <p>
337    * Methods that are <code>static</code>, return <code>void</code>, have
338    * parameters, or are "bridge" methods, are ignored.
339    * <p>
340    * For example, if an object has a method named <code>"getName"</code>, and if
341    * the result of calling <code>object.getName()</code> is
342    * <code>"Larry Fine"</code>, then the JSONObject will contain
343    * <code>"name": "Larry Fine"</code>.
344    * <p>
345    * The {@link JSONPropertyName} annotation can be used on a bean getter to
346    * override key name used in the JSONObject. For example, using the object
347    * above with the <code>getName</code> method, if we annotated it with:
348    * 
349    * <pre>
350    * &#64;JSONPropertyName("FullName")
351    * public String getName()
352    * {
353    *   return this.name;
354    * }
355    * </pre>
356    * 
357    * The resulting JSON object would contain
358    * <code>"FullName": "Larry Fine"</code>
359    * <p>
360    * Similarly, the {@link JSONPropertyName} annotation can be used on non-
361    * <code>get</code> and <code>is</code> methods. We can also override key name
362    * used in the JSONObject as seen below even though the field would normally
363    * be ignored:
364    * 
365    * <pre>
366    * &#64;JSONPropertyName("FullName")
367    * public String fullName()
368    * {
369    *   return this.name;
370    * }
371    * </pre>
372    * 
373    * The resulting JSON object would contain
374    * <code>"FullName": "Larry Fine"</code>
375    * <p>
376    * The {@link JSONPropertyIgnore} annotation can be used to force the bean
377    * property to not be serialized into JSON. If both {@link JSONPropertyIgnore}
378    * and {@link JSONPropertyName} are defined on the same method, a depth
379    * comparison is performed and the one closest to the concrete class being
380    * serialized is used. If both annotations are at the same level, then the
381    * {@link JSONPropertyIgnore} annotation takes precedent and the field is not
382    * serialized. For example, the following declaration would prevent the
383    * <code>getName</code> method from being serialized:
384    * 
385    * <pre>
386    * &#64;JSONPropertyName("FullName")
387    * &#64;JSONPropertyIgnore
388    * public String getName()
389    * {
390    *   return this.name;
391    * }
392    * </pre>
393    * <p>
394    * 
395    * @param bean
396    *          An object that has getter methods that should be used to make a
397    *          JSONObject.
398    */
399   public JSONObject(Object bean)
400   {
401     this();
402     this.populateMap(bean);
403   }
404
405   /**
406    * Construct a JSONObject from an Object, using reflection to find the public
407    * members. The resulting JSONObject's keys will be the strings from the names
408    * array, and the values will be the field values associated with those keys
409    * in the object. If a key is not found or not visible, then it will not be
410    * copied into the new JSONObject.
411    *
412    * @param object
413    *          An object that has fields that should be used to make a
414    *          JSONObject.
415    * @param names
416    *          An array of strings, the names of the fields to be obtained from
417    *          the object.
418    */
419   public JSONObject(Object object, String names[])
420   {
421     this(names.length);
422     Class<?> c = object.getClass();
423     for (int i = 0; i < names.length; i += 1)
424     {
425       String name = names[i];
426       try
427       {
428         this.putOpt(name, c.getField(name).get(object));
429       } catch (Exception ignore)
430       {
431       }
432     }
433   }
434
435   /**
436    * Construct a JSONObject from a source JSON text string. This is the most
437    * commonly used JSONObject constructor.
438    *
439    * @param source
440    *          A string beginning with <code>{</code>&nbsp;<small>(left
441    *          brace)</small> and ending with <code>}</code> &nbsp;<small>(right
442    *          brace)</small>.
443    * @exception JSONException
444    *              If there is a syntax error in the source string or a
445    *              duplicated key.
446    */
447   public JSONObject(String source) throws JSONException
448   {
449     this(new JSONTokener(source));
450   }
451
452   /**
453    * Construct a JSONObject from a ResourceBundle.
454    *
455    * @param baseName
456    *          The ResourceBundle base name.
457    * @param locale
458    *          The Locale to load the ResourceBundle for.
459    * @throws JSONException
460    *           If any JSONExceptions are detected.
461    */
462   public JSONObject(String baseName, Locale locale) throws JSONException
463   {
464     this();
465     ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale,
466             Thread.currentThread().getContextClassLoader());
467
468     // Iterate through the keys in the bundle.
469
470     Enumeration<String> keys = bundle.getKeys();
471     while (keys.hasMoreElements())
472     {
473       Object key = keys.nextElement();
474       if (key != null)
475       {
476
477         // Go through the path, ensuring that there is a nested JSONObject for
478         // each
479         // segment except the last. Add the value using the last segment's name
480         // into
481         // the deepest nested JSONObject.
482
483         String[] path = ((String) key).split("\\.");
484         int last = path.length - 1;
485         JSONObject target = this;
486         for (int i = 0; i < last; i += 1)
487         {
488           String segment = path[i];
489           JSONObject nextTarget = target.optJSONObject(segment);
490           if (nextTarget == null)
491           {
492             nextTarget = new JSONObject();
493             target.put(segment, nextTarget);
494           }
495           target = nextTarget;
496         }
497         target.put(path[last], bundle.getString((String) key));
498       }
499     }
500   }
501
502   /**
503    * Constructor to specify an initial capacity of the internal map. Useful for
504    * library internal calls where we know, or at least can best guess, how big
505    * this JSONObject will be.
506    * 
507    * @param initialCapacity
508    *          initial capacity of the internal map.
509    */
510   protected JSONObject(int initialCapacity)
511   {
512     this.map = new HashMap<String, Object>(initialCapacity);
513   }
514
515   /**
516    * Accumulate values under a key. It is similar to the put method except that
517    * if there is already an object stored under the key then a JSONArray is
518    * stored under the key to hold all of the accumulated values. If there is
519    * already a JSONArray, then the new value is appended to it. In contrast, the
520    * put method replaces the previous value.
521    *
522    * If only one value is accumulated that is not a JSONArray, then the result
523    * will be the same as using put. But if multiple values are accumulated, then
524    * the result will be like append.
525    *
526    * @param key
527    *          A key string.
528    * @param value
529    *          An object to be accumulated under the key.
530    * @return this.
531    * @throws JSONException
532    *           If the value is non-finite number.
533    * @throws NullPointerException
534    *           If the key is <code>null</code>.
535    */
536   public JSONObject accumulate(String key, Object value)
537           throws JSONException
538   {
539     testValidity(value);
540     Object object = this.opt(key);
541     if (object == null)
542     {
543       this.put(key, value instanceof JSONArray ? new JSONArray().put(value)
544               : value);
545     }
546     else if (object instanceof JSONArray)
547     {
548       ((JSONArray) object).put(value);
549     }
550     else
551     {
552       this.put(key, new JSONArray().put(object).put(value));
553     }
554     return this;
555   }
556
557   /**
558    * Append values to the array under a key. If the key does not exist in the
559    * JSONObject, then the key is put in the JSONObject with its value being a
560    * JSONArray containing the value parameter. If the key was already associated
561    * with a JSONArray, then the value parameter is appended to it.
562    *
563    * @param key
564    *          A key string.
565    * @param value
566    *          An object to be accumulated under the key.
567    * @return this.
568    * @throws JSONException
569    *           If the value is non-finite number or if the current value
570    *           associated with the key is not a JSONArray.
571    * @throws NullPointerException
572    *           If the key is <code>null</code>.
573    */
574   public JSONObject append(String key, Object value) throws JSONException
575   {
576     testValidity(value);
577     Object object = this.opt(key);
578     if (object == null)
579     {
580       this.put(key, new JSONArray().put(value));
581     }
582     else if (object instanceof JSONArray)
583     {
584       this.put(key, ((JSONArray) object).put(value));
585     }
586     else
587     {
588       throw new JSONException(
589               "JSONObject[" + key + "] is not a JSONArray.");
590     }
591     return this;
592   }
593
594   /**
595    * Produce a string from a double. The string "null" will be returned if the
596    * number is not finite.
597    *
598    * @param d
599    *          A double.
600    * @return A String.
601    */
602   public static String doubleToString(double d)
603   {
604     if (Double.isInfinite(d) || Double.isNaN(d))
605     {
606       return "null";
607     }
608
609     // Shave off trailing zeros and decimal point, if possible.
610
611     String string = Double.toString(d);
612     if (string.indexOf('.') > 0 && string.indexOf('e') < 0
613             && string.indexOf('E') < 0)
614     {
615       while (string.endsWith("0"))
616       {
617         string = string.substring(0, string.length() - 1);
618       }
619       if (string.endsWith("."))
620       {
621         string = string.substring(0, string.length() - 1);
622       }
623     }
624     return string;
625   }
626
627   /**
628    * Get the value object associated with a key.
629    *
630    * @param key
631    *          A key string.
632    * @return The object associated with the key.
633    * @throws JSONException
634    *           if the key is not found.
635    */
636   public Object get(String key) throws JSONException
637   {
638     if (key == null)
639     {
640       throw new JSONException("Null key.");
641     }
642     Object object = this.opt(key);
643     if (object == null)
644     {
645       throw new JSONException("JSONObject[" + quote(key) + "] not found.");
646     }
647     return object;
648   }
649
650   /**
651    * Get the enum value associated with a key.
652    * 
653    * @param clazz
654    *          The type of enum to retrieve.
655    * @param key
656    *          A key string.
657    * @return The enum value associated with the key
658    * @throws JSONException
659    *           if the key is not found or if the value cannot be converted to an
660    *           enum.
661    */
662   public <E extends Enum<E>> E getEnum(Class<E> clazz, String key)
663           throws JSONException
664   {
665     E val = optEnum(clazz, key);
666     if (val == null)
667     {
668       // JSONException should really take a throwable argument.
669       // If it did, I would re-implement this with the Enum.valueOf
670       // method and place any thrown exception in the JSONException
671       throw new JSONException(
672               "JSONObject[" + quote(key) + "] is not an enum of type "
673                       + quote(clazz.getSimpleName()) + ".");
674     }
675     return val;
676   }
677
678   /**
679    * Get the boolean value associated with a key.
680    *
681    * @param key
682    *          A key string.
683    * @return The truth.
684    * @throws JSONException
685    *           if the value is not a Boolean or the String "true" or "false".
686    */
687   public boolean getBoolean(String key) throws JSONException
688   {
689     Object object = this.get(key);
690     if (object.equals(Boolean.FALSE) || (object instanceof String
691             && ((String) object).equalsIgnoreCase("false")))
692     {
693       return false;
694     }
695     else if (object.equals(Boolean.TRUE) || (object instanceof String
696             && ((String) object).equalsIgnoreCase("true")))
697     {
698       return true;
699     }
700     throw new JSONException(
701             "JSONObject[" + quote(key) + "] is not a Boolean.");
702   }
703
704   /**
705    * Get the BigInteger value associated with a key.
706    *
707    * @param key
708    *          A key string.
709    * @return The numeric value.
710    * @throws JSONException
711    *           if the key is not found or if the value cannot be converted to
712    *           BigInteger.
713    */
714   public BigInteger getBigInteger(String key) throws JSONException
715   {
716     Object object = this.get(key);
717     try
718     {
719       return new BigInteger(object.toString());
720     } catch (Exception e)
721     {
722       throw new JSONException("JSONObject[" + quote(key)
723               + "] could not be converted to BigInteger.", e);
724     }
725   }
726
727   /**
728    * Get the BigDecimal value associated with a key.
729    *
730    * @param key
731    *          A key string.
732    * @return The numeric value.
733    * @throws JSONException
734    *           if the key is not found or if the value cannot be converted to
735    *           BigDecimal.
736    */
737   public BigDecimal getBigDecimal(String key) throws JSONException
738   {
739     Object object = this.get(key);
740     if (object instanceof BigDecimal)
741     {
742       return (BigDecimal) object;
743     }
744     try
745     {
746       return new BigDecimal(object.toString());
747     } catch (Exception e)
748     {
749       throw new JSONException("JSONObject[" + quote(key)
750               + "] could not be converted to BigDecimal.", e);
751     }
752   }
753
754   /**
755    * Get the double value associated with a key.
756    *
757    * @param key
758    *          A key string.
759    * @return The numeric value.
760    * @throws JSONException
761    *           if the key is not found or if the value is not a Number object
762    *           and cannot be converted to a number.
763    */
764   public double getDouble(String key) throws JSONException
765   {
766     Object object = this.get(key);
767     try
768     {
769       return object instanceof Number ? ((Number) object).doubleValue()
770               : Double.parseDouble(object.toString());
771     } catch (Exception e)
772     {
773       throw new JSONException(
774               "JSONObject[" + quote(key) + "] is not a number.", e);
775     }
776   }
777
778   /**
779    * Get the float value associated with a key.
780    *
781    * @param key
782    *          A key string.
783    * @return The numeric value.
784    * @throws JSONException
785    *           if the key is not found or if the value is not a Number object
786    *           and cannot be converted to a number.
787    */
788   public float getFloat(String key) throws JSONException
789   {
790     Object object = this.get(key);
791     try
792     {
793       return object instanceof Number ? ((Number) object).floatValue()
794               : Float.parseFloat(object.toString());
795     } catch (Exception e)
796     {
797       throw new JSONException(
798               "JSONObject[" + quote(key) + "] is not a number.", e);
799     }
800   }
801
802   /**
803    * Get the Number value associated with a key.
804    *
805    * @param key
806    *          A key string.
807    * @return The numeric value.
808    * @throws JSONException
809    *           if the key is not found or if the value is not a Number object
810    *           and cannot be converted to a number.
811    */
812   public Number getNumber(String key) throws JSONException
813   {
814     Object object = this.get(key);
815     try
816     {
817       if (object instanceof Number)
818       {
819         return (Number) object;
820       }
821       return stringToNumber(object.toString());
822     } catch (Exception e)
823     {
824       throw new JSONException(
825               "JSONObject[" + quote(key) + "] is not a number.", e);
826     }
827   }
828
829   /**
830    * Get the int value associated with a key.
831    *
832    * @param key
833    *          A key string.
834    * @return The integer value.
835    * @throws JSONException
836    *           if the key is not found or if the value cannot be converted to an
837    *           integer.
838    */
839   public int getInt(String key) throws JSONException
840   {
841     Object object = this.get(key);
842     try
843     {
844       return object instanceof Number ? ((Number) object).intValue()
845               : Integer.parseInt((String) object);
846     } catch (Exception e)
847     {
848       throw new JSONException(
849               "JSONObject[" + quote(key) + "] is not an int.", e);
850     }
851   }
852
853   /**
854    * Get the JSONArray value associated with a key.
855    *
856    * @param key
857    *          A key string.
858    * @return A JSONArray which is the value.
859    * @throws JSONException
860    *           if the key is not found or if the value is not a JSONArray.
861    */
862   public JSONArray getJSONArray(String key) throws JSONException
863   {
864     Object object = this.get(key);
865     if (object instanceof JSONArray)
866     {
867       return (JSONArray) object;
868     }
869     throw new JSONException(
870             "JSONObject[" + quote(key) + "] is not a JSONArray.");
871   }
872
873   /**
874    * Get the JSONObject value associated with a key.
875    *
876    * @param key
877    *          A key string.
878    * @return A JSONObject which is the value.
879    * @throws JSONException
880    *           if the key is not found or if the value is not a JSONObject.
881    */
882   public JSONObject getJSONObject(String key) throws JSONException
883   {
884     Object object = this.get(key);
885     if (object instanceof JSONObject)
886     {
887       return (JSONObject) object;
888     }
889     throw new JSONException(
890             "JSONObject[" + quote(key) + "] is not a JSONObject.");
891   }
892
893   /**
894    * Get the long value associated with a key.
895    *
896    * @param key
897    *          A key string.
898    * @return The long value.
899    * @throws JSONException
900    *           if the key is not found or if the value cannot be converted to a
901    *           long.
902    */
903   public long getLong(String key) throws JSONException
904   {
905     Object object = this.get(key);
906     try
907     {
908       return object instanceof Number ? ((Number) object).longValue()
909               : Long.parseLong((String) object);
910     } catch (Exception e)
911     {
912       throw new JSONException(
913               "JSONObject[" + quote(key) + "] is not a long.", e);
914     }
915   }
916
917   /**
918    * Get an array of field names from a JSONObject.
919    *
920    * @return An array of field names, or null if there are no names.
921    */
922   public static String[] getNames(JSONObject jo)
923   {
924     if (jo.isEmpty())
925     {
926       return null;
927     }
928     return jo.keySet().toArray(new String[jo.length()]);
929   }
930
931   /**
932    * Get an array of field names from an Object.
933    *
934    * @return An array of field names, or null if there are no names.
935    */
936   public static String[] getNames(Object object)
937   {
938     if (object == null)
939     {
940       return null;
941     }
942     Class<?> klass = object.getClass();
943     Field[] fields = klass.getFields();
944     int length = fields.length;
945     if (length == 0)
946     {
947       return null;
948     }
949     String[] names = new String[length];
950     for (int i = 0; i < length; i += 1)
951     {
952       names[i] = fields[i].getName();
953     }
954     return names;
955   }
956
957   /**
958    * Get the string associated with a key.
959    *
960    * @param key
961    *          A key string.
962    * @return A string which is the value.
963    * @throws JSONException
964    *           if there is no string value for the key.
965    */
966   public String getString(String key) throws JSONException
967   {
968     Object object = this.get(key);
969     if (object instanceof String)
970     {
971       return (String) object;
972     }
973     throw new JSONException("JSONObject[" + quote(key) + "] not a string.");
974   }
975
976   /**
977    * Determine if the JSONObject contains a specific key.
978    *
979    * @param key
980    *          A key string.
981    * @return true if the key exists in the JSONObject.
982    */
983   public boolean has(String key)
984   {
985     return this.map.containsKey(key);
986   }
987
988   /**
989    * Increment a property of a JSONObject. If there is no such property, create
990    * one with a value of 1. If there is such a property, and if it is an
991    * Integer, Long, Double, or Float, then add one to it.
992    *
993    * @param key
994    *          A key string.
995    * @return this.
996    * @throws JSONException
997    *           If there is already a property with this name that is not an
998    *           Integer, Long, Double, or Float.
999    */
1000   public JSONObject increment(String key) throws JSONException
1001   {
1002     Object value = this.opt(key);
1003     if (value == null)
1004     {
1005       this.put(key, 1);
1006     }
1007     else if (value instanceof BigInteger)
1008     {
1009       this.put(key, ((BigInteger) value).add(BigInteger.ONE));
1010     }
1011     else if (value instanceof BigDecimal)
1012     {
1013       this.put(key, ((BigDecimal) value).add(BigDecimal.ONE));
1014     }
1015     else if (value instanceof Integer)
1016     {
1017       this.put(key, ((Integer) value).intValue() + 1);
1018     }
1019     else if (value instanceof Long)
1020     {
1021       this.put(key, ((Long) value).longValue() + 1L);
1022     }
1023     else if (value instanceof Double)
1024     {
1025       this.put(key, ((Double) value).doubleValue() + 1.0d);
1026     }
1027     else if (value instanceof Float)
1028     {
1029       this.put(key, ((Float) value).floatValue() + 1.0f);
1030     }
1031     else
1032     {
1033       throw new JSONException("Unable to increment [" + quote(key) + "].");
1034     }
1035     return this;
1036   }
1037
1038   /**
1039    * Determine if the value associated with the key is <code>null</code> or if
1040    * there is no value.
1041    *
1042    * @param key
1043    *          A key string.
1044    * @return true if there is no value associated with the key or if the value
1045    *         is the JSONObject.NULL object.
1046    */
1047   public boolean isNull(String key)
1048   {
1049     return JSONObject.NULL.equals(this.opt(key));
1050   }
1051
1052   /**
1053    * Get an enumeration of the keys of the JSONObject. Modifying this key Set
1054    * will also modify the JSONObject. Use with caution.
1055    *
1056    * @see Set#iterator()
1057    * 
1058    * @return An iterator of the keys.
1059    */
1060   public Iterator<String> keys()
1061   {
1062     return this.keySet().iterator();
1063   }
1064
1065   /**
1066    * Get a set of keys of the JSONObject. Modifying this key Set will also
1067    * modify the JSONObject. Use with caution.
1068    *
1069    * @see Map#keySet()
1070    *
1071    * @return A keySet.
1072    */
1073   public Set<String> keySet()
1074   {
1075     return this.map.keySet();
1076   }
1077
1078   /**
1079    * Get a set of entries of the JSONObject. These are raw values and may not
1080    * match what is returned by the JSONObject get* and opt* functions. Modifying
1081    * the returned EntrySet or the Entry objects contained therein will modify
1082    * the backing JSONObject. This does not return a clone or a read-only view.
1083    * 
1084    * Use with caution.
1085    *
1086    * @see Map#entrySet()
1087    *
1088    * @return An Entry Set
1089    */
1090   protected Set<Entry<String, Object>> entrySet()
1091   {
1092     return this.map.entrySet();
1093   }
1094
1095   /**
1096    * Get the number of keys stored in the JSONObject.
1097    *
1098    * @return The number of keys in the JSONObject.
1099    */
1100   public int length()
1101   {
1102     return this.map.size();
1103   }
1104
1105   /**
1106    * Check if JSONObject is empty.
1107    *
1108    * @return true if JSONObject is empty, otherwise false.
1109    */
1110   public boolean isEmpty()
1111   {
1112     return map.isEmpty();
1113   }
1114
1115   /**
1116    * Produce a JSONArray containing the names of the elements of this
1117    * JSONObject.
1118    *
1119    * @return A JSONArray containing the key strings, or null if the JSONObject
1120    *         is empty.
1121    */
1122   public JSONArray names()
1123   {
1124     if (this.map.isEmpty())
1125     {
1126       return null;
1127     }
1128     return new JSONArray(this.map.keySet());
1129   }
1130
1131   /**
1132    * Produce a string from a Number.
1133    *
1134    * @param number
1135    *          A Number
1136    * @return A String.
1137    * @throws JSONException
1138    *           If n is a non-finite number.
1139    */
1140   public static String numberToString(Number number) throws JSONException
1141   {
1142     if (number == null)
1143     {
1144       throw new JSONException("Null pointer");
1145     }
1146     testValidity(number);
1147
1148     // Shave off trailing zeros and decimal point, if possible.
1149
1150     String string = number.toString();
1151     if (string.indexOf('.') > 0 && string.indexOf('e') < 0
1152             && string.indexOf('E') < 0)
1153     {
1154       while (string.endsWith("0"))
1155       {
1156         string = string.substring(0, string.length() - 1);
1157       }
1158       if (string.endsWith("."))
1159       {
1160         string = string.substring(0, string.length() - 1);
1161       }
1162     }
1163     return string;
1164   }
1165
1166   /**
1167    * Get an optional value associated with a key.
1168    *
1169    * @param key
1170    *          A key string.
1171    * @return An object which is the value, or null if there is no value.
1172    */
1173   public Object opt(String key)
1174   {
1175     return key == null ? null : this.map.get(key);
1176   }
1177
1178   /**
1179    * Get the enum value associated with a key.
1180    * 
1181    * @param clazz
1182    *          The type of enum to retrieve.
1183    * @param key
1184    *          A key string.
1185    * @return The enum value associated with the key or null if not found
1186    */
1187   public <E extends Enum<E>> E optEnum(Class<E> clazz, String key)
1188   {
1189     return this.optEnum(clazz, key, null);
1190   }
1191
1192   /**
1193    * Get the enum value associated with a key.
1194    * 
1195    * @param clazz
1196    *          The type of enum to retrieve.
1197    * @param key
1198    *          A key string.
1199    * @param defaultValue
1200    *          The default in case the value is not found
1201    * @return The enum value associated with the key or defaultValue if the value
1202    *         is not found or cannot be assigned to <code>clazz</code>
1203    */
1204   public <E extends Enum<E>> E optEnum(Class<E> clazz, String key,
1205           E defaultValue)
1206   {
1207     try
1208     {
1209       Object val = this.opt(key);
1210       if (NULL.equals(val))
1211       {
1212         return defaultValue;
1213       }
1214       if (clazz.isAssignableFrom(val.getClass()))
1215       {
1216         // we just checked it!
1217         @SuppressWarnings("unchecked")
1218         E myE = (E) val;
1219         return myE;
1220       }
1221       return Enum.valueOf(clazz, val.toString());
1222     } catch (IllegalArgumentException e)
1223     {
1224       return defaultValue;
1225     } catch (NullPointerException e)
1226     {
1227       return defaultValue;
1228     }
1229   }
1230
1231   /**
1232    * Get an optional boolean associated with a key. It returns false if there is
1233    * no such key, or if the value is not Boolean.TRUE or the String "true".
1234    *
1235    * @param key
1236    *          A key string.
1237    * @return The truth.
1238    */
1239   public boolean optBoolean(String key)
1240   {
1241     return this.optBoolean(key, false);
1242   }
1243
1244   /**
1245    * Get an optional boolean associated with a key. It returns the defaultValue
1246    * if there is no such key, or if it is not a Boolean or the String "true" or
1247    * "false" (case insensitive).
1248    *
1249    * @param key
1250    *          A key string.
1251    * @param defaultValue
1252    *          The default.
1253    * @return The truth.
1254    */
1255   public boolean optBoolean(String key, boolean defaultValue)
1256   {
1257     Object val = this.opt(key);
1258     if (NULL.equals(val))
1259     {
1260       return defaultValue;
1261     }
1262     if (val instanceof Boolean)
1263     {
1264       return ((Boolean) val).booleanValue();
1265     }
1266     try
1267     {
1268       // we'll use the get anyway because it does string conversion.
1269       return this.getBoolean(key);
1270     } catch (Exception e)
1271     {
1272       return defaultValue;
1273     }
1274   }
1275
1276   /**
1277    * Get an optional BigDecimal associated with a key, or the defaultValue if
1278    * there is no such key or if its value is not a number. If the value is a
1279    * string, an attempt will be made to evaluate it as a number.
1280    *
1281    * @param key
1282    *          A key string.
1283    * @param defaultValue
1284    *          The default.
1285    * @return An object which is the value.
1286    */
1287   public BigDecimal optBigDecimal(String key, BigDecimal defaultValue)
1288   {
1289     Object val = this.opt(key);
1290     if (NULL.equals(val))
1291     {
1292       return defaultValue;
1293     }
1294     if (val instanceof BigDecimal)
1295     {
1296       return (BigDecimal) val;
1297     }
1298     if (val instanceof BigInteger)
1299     {
1300       return new BigDecimal((BigInteger) val);
1301     }
1302     if (val instanceof Double || val instanceof Float)
1303     {
1304       return new BigDecimal(((Number) val).doubleValue());
1305     }
1306     if (val instanceof Long || val instanceof Integer
1307             || val instanceof Short || val instanceof Byte)
1308     {
1309       return new BigDecimal(((Number) val).longValue());
1310     }
1311     // don't check if it's a string in case of unchecked Number subclasses
1312     try
1313     {
1314       return new BigDecimal(val.toString());
1315     } catch (Exception e)
1316     {
1317       return defaultValue;
1318     }
1319   }
1320
1321   /**
1322    * Get an optional BigInteger associated with a key, or the defaultValue if
1323    * there is no such key or if its value is not a number. If the value is a
1324    * string, an attempt will be made to evaluate it as a number.
1325    *
1326    * @param key
1327    *          A key string.
1328    * @param defaultValue
1329    *          The default.
1330    * @return An object which is the value.
1331    */
1332   public BigInteger optBigInteger(String key, BigInteger defaultValue)
1333   {
1334     Object val = this.opt(key);
1335     if (NULL.equals(val))
1336     {
1337       return defaultValue;
1338     }
1339     if (val instanceof BigInteger)
1340     {
1341       return (BigInteger) val;
1342     }
1343     if (val instanceof BigDecimal)
1344     {
1345       return ((BigDecimal) val).toBigInteger();
1346     }
1347     if (val instanceof Double || val instanceof Float)
1348     {
1349       return new BigDecimal(((Number) val).doubleValue()).toBigInteger();
1350     }
1351     if (val instanceof Long || val instanceof Integer
1352             || val instanceof Short || val instanceof Byte)
1353     {
1354       return BigInteger.valueOf(((Number) val).longValue());
1355     }
1356     // don't check if it's a string in case of unchecked Number subclasses
1357     try
1358     {
1359       // the other opt functions handle implicit conversions, i.e.
1360       // jo.put("double",1.1d);
1361       // jo.optInt("double"); -- will return 1, not an error
1362       // this conversion to BigDecimal then to BigInteger is to maintain
1363       // that type cast support that may truncate the decimal.
1364       final String valStr = val.toString();
1365       if (isDecimalNotation(valStr))
1366       {
1367         return new BigDecimal(valStr).toBigInteger();
1368       }
1369       return new BigInteger(valStr);
1370     } catch (Exception e)
1371     {
1372       return defaultValue;
1373     }
1374   }
1375
1376   /**
1377    * Get an optional double associated with a key, or NaN if there is no such
1378    * key or if its value is not a number. If the value is a string, an attempt
1379    * will be made to evaluate it as a number.
1380    *
1381    * @param key
1382    *          A string which is the key.
1383    * @return An object which is the value.
1384    */
1385   public double optDouble(String key)
1386   {
1387     return this.optDouble(key, Double.NaN);
1388   }
1389
1390   /**
1391    * Get an optional double associated with a key, or the defaultValue if there
1392    * is no such key or if its value is not a number. If the value is a string,
1393    * an attempt will be made to evaluate it as a number.
1394    *
1395    * @param key
1396    *          A key string.
1397    * @param defaultValue
1398    *          The default.
1399    * @return An object which is the value.
1400    */
1401   public double optDouble(String key, double defaultValue)
1402   {
1403     Object val = this.opt(key);
1404     if (NULL.equals(val))
1405     {
1406       return defaultValue;
1407     }
1408     if (val instanceof Number)
1409     {
1410       return ((Number) val).doubleValue();
1411     }
1412     if (val instanceof String)
1413     {
1414       try
1415       {
1416         return Double.parseDouble((String) val);
1417       } catch (Exception e)
1418       {
1419         return defaultValue;
1420       }
1421     }
1422     return defaultValue;
1423   }
1424
1425   /**
1426    * Get the optional double value associated with an index. NaN is returned if
1427    * there is no value for the index, or if the value is not a number and cannot
1428    * be converted to a number.
1429    *
1430    * @param key
1431    *          A key string.
1432    * @return The value.
1433    */
1434   public float optFloat(String key)
1435   {
1436     return this.optFloat(key, Float.NaN);
1437   }
1438
1439   /**
1440    * Get the optional double value associated with an index. The defaultValue is
1441    * returned if there is no value for the index, or if the value is not a
1442    * number and cannot be converted to a number.
1443    *
1444    * @param key
1445    *          A key string.
1446    * @param defaultValue
1447    *          The default value.
1448    * @return The value.
1449    */
1450   public float optFloat(String key, float defaultValue)
1451   {
1452     Object val = this.opt(key);
1453     if (JSONObject.NULL.equals(val))
1454     {
1455       return defaultValue;
1456     }
1457     if (val instanceof Number)
1458     {
1459       return ((Number) val).floatValue();
1460     }
1461     if (val instanceof String)
1462     {
1463       try
1464       {
1465         return Float.parseFloat((String) val);
1466       } catch (Exception e)
1467       {
1468         return defaultValue;
1469       }
1470     }
1471     return defaultValue;
1472   }
1473
1474   /**
1475    * Get an optional int value associated with a key, or zero if there is no
1476    * such key or if the value is not a number. If the value is a string, an
1477    * attempt will be made to evaluate it as a number.
1478    *
1479    * @param key
1480    *          A key string.
1481    * @return An object which is the value.
1482    */
1483   public int optInt(String key)
1484   {
1485     return this.optInt(key, 0);
1486   }
1487
1488   /**
1489    * Get an optional int value associated with a key, or the default if there is
1490    * no such key or if the value is not a number. If the value is a string, an
1491    * attempt will be made to evaluate it as a number.
1492    *
1493    * @param key
1494    *          A key string.
1495    * @param defaultValue
1496    *          The default.
1497    * @return An object which is the value.
1498    */
1499   public int optInt(String key, int defaultValue)
1500   {
1501     Object val = this.opt(key);
1502     if (NULL.equals(val))
1503     {
1504       return defaultValue;
1505     }
1506     if (val instanceof Number)
1507     {
1508       return ((Number) val).intValue();
1509     }
1510
1511     if (val instanceof String)
1512     {
1513       try
1514       {
1515         return new BigDecimal((String) val).intValue();
1516       } catch (Exception e)
1517       {
1518         return defaultValue;
1519       }
1520     }
1521     return defaultValue;
1522   }
1523
1524   /**
1525    * Get an optional JSONArray associated with a key. It returns null if there
1526    * is no such key, or if its value is not a JSONArray.
1527    *
1528    * @param key
1529    *          A key string.
1530    * @return A JSONArray which is the value.
1531    */
1532   public JSONArray optJSONArray(String key)
1533   {
1534     Object o = this.opt(key);
1535     return o instanceof JSONArray ? (JSONArray) o : null;
1536   }
1537
1538   /**
1539    * Get an optional JSONObject associated with a key. It returns null if there
1540    * is no such key, or if its value is not a JSONObject.
1541    *
1542    * @param key
1543    *          A key string.
1544    * @return A JSONObject which is the value.
1545    */
1546   public JSONObject optJSONObject(String key)
1547   {
1548     Object object = this.opt(key);
1549     return object instanceof JSONObject ? (JSONObject) object : null;
1550   }
1551
1552   /**
1553    * Get an optional long value associated with a key, or zero if there is no
1554    * such key or if the value is not a number. If the value is a string, an
1555    * attempt will be made to evaluate it as a number.
1556    *
1557    * @param key
1558    *          A key string.
1559    * @return An object which is the value.
1560    */
1561   public long optLong(String key)
1562   {
1563     return this.optLong(key, 0);
1564   }
1565
1566   /**
1567    * Get an optional long value associated with a key, or the default if there
1568    * is no such key or if the value is not a number. If the value is a string,
1569    * an attempt will be made to evaluate it as a number.
1570    *
1571    * @param key
1572    *          A key string.
1573    * @param defaultValue
1574    *          The default.
1575    * @return An object which is the value.
1576    */
1577   public long optLong(String key, long defaultValue)
1578   {
1579     Object val = this.opt(key);
1580     if (NULL.equals(val))
1581     {
1582       return defaultValue;
1583     }
1584     if (val instanceof Number)
1585     {
1586       return ((Number) val).longValue();
1587     }
1588
1589     if (val instanceof String)
1590     {
1591       try
1592       {
1593         return new BigDecimal((String) val).longValue();
1594       } catch (Exception e)
1595       {
1596         return defaultValue;
1597       }
1598     }
1599     return defaultValue;
1600   }
1601
1602   /**
1603    * Get an optional {@link Number} value associated with a key, or
1604    * <code>null</code> if there is no such key or if the value is not a number.
1605    * If the value is a string, an attempt will be made to evaluate it as a
1606    * number ({@link BigDecimal}). This method would be used in cases where type
1607    * coercion of the number value is unwanted.
1608    *
1609    * @param key
1610    *          A key string.
1611    * @return An object which is the value.
1612    */
1613   public Number optNumber(String key)
1614   {
1615     return this.optNumber(key, null);
1616   }
1617
1618   /**
1619    * Get an optional {@link Number} value associated with a key, or the default
1620    * if there is no such key or if the value is not a number. If the value is a
1621    * string, an attempt will be made to evaluate it as a number. This method
1622    * would be used in cases where type coercion of the number value is unwanted.
1623    *
1624    * @param key
1625    *          A key string.
1626    * @param defaultValue
1627    *          The default.
1628    * @return An object which is the value.
1629    */
1630   public Number optNumber(String key, Number defaultValue)
1631   {
1632     Object val = this.opt(key);
1633     if (NULL.equals(val))
1634     {
1635       return defaultValue;
1636     }
1637     if (val instanceof Number)
1638     {
1639       return (Number) val;
1640     }
1641
1642     if (val instanceof String)
1643     {
1644       try
1645       {
1646         return stringToNumber((String) val);
1647       } catch (Exception e)
1648       {
1649         return defaultValue;
1650       }
1651     }
1652     return defaultValue;
1653   }
1654
1655   /**
1656    * Get an optional string associated with a key. It returns an empty string if
1657    * there is no such key. If the value is not a string and is not null, then it
1658    * is converted to a string.
1659    *
1660    * @param key
1661    *          A key string.
1662    * @return A string which is the value.
1663    */
1664   public String optString(String key)
1665   {
1666     return this.optString(key, "");
1667   }
1668
1669   /**
1670    * Get an optional string associated with a key. It returns the defaultValue
1671    * if there is no such key.
1672    *
1673    * @param key
1674    *          A key string.
1675    * @param defaultValue
1676    *          The default.
1677    * @return A string which is the value.
1678    */
1679   public String optString(String key, String defaultValue)
1680   {
1681     Object object = this.opt(key);
1682     return NULL.equals(object) ? defaultValue : object.toString();
1683   }
1684
1685   /**
1686    * Populates the internal map of the JSONObject with the bean properties. The
1687    * bean can not be recursive.
1688    *
1689    * @see JSONObject#JSONObject(Object)
1690    *
1691    * @param bean
1692    *          the bean
1693    */
1694   private void populateMap(Object bean)
1695   {
1696     Class<?> klass = bean.getClass();
1697
1698     // If klass is a System class then set includeSuperClass to false.
1699
1700     boolean includeSuperClass = klass.getClassLoader() != null;
1701
1702     Method[] methods = includeSuperClass ? klass.getMethods()
1703             : klass.getDeclaredMethods();
1704     for (final Method method : methods)
1705     {
1706       final int modifiers = method.getModifiers();
1707       if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)
1708               && method.getParameterTypes().length == 0
1709               && !method.isBridge() && method.getReturnType() != Void.TYPE
1710               && isValidMethodName(method.getName()))
1711       {
1712         final String key = getKeyNameFromMethod(method);
1713         if (key != null && !key.isEmpty())
1714         {
1715           try
1716           {
1717             final Object result = method.invoke(bean);
1718             if (result != null)
1719             {
1720               this.map.put(key, wrap(result));
1721               // we don't use the result anywhere outside of wrap
1722               // if it's a resource we should be sure to close it
1723               // after calling toString
1724               if (result instanceof Closeable)
1725               {
1726                 try
1727                 {
1728                   ((Closeable) result).close();
1729                 } catch (IOException ignore)
1730                 {
1731                 }
1732               }
1733             }
1734           } catch (IllegalAccessException ignore)
1735           {
1736           } catch (IllegalArgumentException ignore)
1737           {
1738           } catch (InvocationTargetException ignore)
1739           {
1740           }
1741         }
1742       }
1743     }
1744   }
1745
1746   private boolean isValidMethodName(String name)
1747   {
1748     return !"getClass".equals(name) && !"getDeclaringClass".equals(name);
1749   }
1750
1751   private String getKeyNameFromMethod(Method method)
1752   {
1753     final int ignoreDepth = -1;// getAnnotationDepth(method,
1754                                // JSONPropertyIgnore.class);
1755     // if (ignoreDepth > 0) {
1756     // final int forcedNameDepth = getAnnotationDepth(method,
1757     // JSONPropertyName.class);
1758     // if (forcedNameDepth < 0 || ignoreDepth <= forcedNameDepth) {
1759     // // the hierarchy asked to ignore, and the nearest name override
1760     // // was higher or non-existent
1761     // return null;
1762     // }
1763     // }
1764     // JSONPropertyName annotation = getAnnotation(method,
1765     // JSONPropertyName.class);
1766     // if (annotation != null && annotation.value() != null &&
1767     // !annotation.value().isEmpty()) {
1768     // return annotation.value();
1769     // }
1770     String key;
1771     final String name = method.getName();
1772     if (name.startsWith("get") && name.length() > 3)
1773     {
1774       key = name.substring(3);
1775     }
1776     else if (name.startsWith("is") && name.length() > 2)
1777     {
1778       key = name.substring(2);
1779     }
1780     else
1781     {
1782       return null;
1783     }
1784     // if the first letter in the key is not uppercase, then skip.
1785     // This is to maintain backwards compatibility before PR406
1786     // (https://github.com/stleary/JSON-java/pull/406/)
1787     if (Character.isLowerCase(key.charAt(0)))
1788     {
1789       return null;
1790     }
1791     if (key.length() == 1)
1792     {
1793       key = key.toLowerCase(Locale.ROOT);
1794     }
1795     else if (!Character.isUpperCase(key.charAt(1)))
1796     {
1797       key = key.substring(0, 1).toLowerCase(Locale.ROOT) + key.substring(1);
1798     }
1799     return (/** @j2sNative 1 ? key.split("$")[0] : */
1800     key);
1801   }
1802
1803   // /**
1804   // * Searches the class hierarchy to see if the method or it's super
1805   // * implementations and interfaces has the annotation.
1806   // *
1807   // * @param <A>
1808   // * type of the annotation
1809   // *
1810   // * @param m
1811   // * method to check
1812   // * @param annotationClass
1813   // * annotation to look for
1814   // * @return the {@link Annotation} if the annotation exists on the current
1815   // method
1816   // * or one of it's super class definitions
1817   // */
1818   // private static <A extends Annotation> A getAnnotation(final Method m, final
1819   // Class<A> annotationClass) {
1820   // return null;
1821   // // if we have invalid data the result is null
1822   // if (true || m == null || annotationClass == null) {
1823   // return null;
1824   // }
1825   //
1826   // if (m.isAnnotationPresent(annotationClass)) {
1827   // return m.getAnnotation(annotationClass);
1828   // }
1829   //
1830   // // if we've already reached the Object class, return null;
1831   // Class<?> c = m.getDeclaringClass();
1832   // if (c.getSuperclass() == null) {
1833   // return null;
1834   // }
1835   //
1836   // // check directly implemented interfaces for the method being checked
1837   // for (Class<?> i : c.getInterfaces()) {
1838   // try {
1839   // Method im = i.getMethod(m.getName(), m.getParameterTypes());
1840   // return getAnnotation(im, annotationClass);
1841   // } catch (final SecurityException ex) {
1842   // continue;
1843   // } catch (final NoSuchMethodException ex) {
1844   // continue;
1845   // }
1846   // }
1847   //
1848   // try {
1849   // return getAnnotation(
1850   // c.getSuperclass().getMethod(m.getName(), m.getParameterTypes()),
1851   // annotationClass);
1852   // } catch (final SecurityException ex) {
1853   // return null;
1854   // } catch (final NoSuchMethodException ex) {
1855   // return null;
1856   // }
1857   // }
1858   //
1859   // /**
1860   // * Searches the class hierarchy to see if the method or it's super
1861   // * implementations and interfaces has the annotation. Returns the depth of
1862   // the
1863   // * annotation in the hierarchy.
1864   // *
1865   // * @param <A>
1866   // * type of the annotation
1867   // *
1868   // * @param m
1869   // * method to check
1870   // * @param annotationClass
1871   // * annotation to look for
1872   // * @return Depth of the annotation or -1 if the annotation is not on the
1873   // method.
1874   // */
1875   // private static int getAnnotationDepth(final Method m, final Class<? extends
1876   // Annotation> annotationClass) {
1877   // // if we have invalid data the result is -1
1878   // if (m == null || annotationClass == null) {
1879   // return -1;
1880   // }
1881   // if (m.isAnnotationPresent(annotationClass)) {
1882   // return 1;
1883   // }
1884   //
1885   // // if we've already reached the Object class, return -1;
1886   // Class<?> c = m.getDeclaringClass();
1887   // if (c.getSuperclass() == null) {
1888   // return -1;
1889   // }
1890   //
1891   // // check directly implemented interfaces for the method being checked
1892   // for (Class<?> i : c.getInterfaces()) {
1893   // try {
1894   // Method im = i.getMethod(m.getName(), m.getParameterTypes());
1895   // int d = getAnnotationDepth(im, annotationClass);
1896   // if (d > 0) {
1897   // // since the annotation was on the interface, add 1
1898   // return d + 1;
1899   // }
1900   // } catch (final SecurityException ex) {
1901   // continue;
1902   // } catch (final NoSuchMethodException ex) {
1903   // continue;
1904   // }
1905   // }
1906   //
1907   // try {
1908   // int d = getAnnotationDepth(
1909   // c.getSuperclass().getMethod(m.getName(), m.getParameterTypes()),
1910   // annotationClass);
1911   // if (d > 0) {
1912   // // since the annotation was on the superclass, add 1
1913   // return d + 1;
1914   // }
1915   // return -1;
1916   // } catch (final SecurityException ex) {
1917   // return -1;
1918   // } catch (final NoSuchMethodException ex) {
1919   // return -1;
1920   // }
1921   // }
1922
1923   /**
1924    * Put a key/boolean pair in the JSONObject.
1925    *
1926    * @param key
1927    *          A key string.
1928    * @param value
1929    *          A boolean which is the value.
1930    * @return this.
1931    * @throws JSONException
1932    *           If the value is non-finite number.
1933    * @throws NullPointerException
1934    *           If the key is <code>null</code>.
1935    */
1936   public JSONObject put(String key, boolean value) throws JSONException
1937   {
1938     return this.put(key, value ? Boolean.TRUE : Boolean.FALSE);
1939   }
1940
1941   /**
1942    * Put a key/value pair in the JSONObject, where the value will be a JSONArray
1943    * which is produced from a Collection.
1944    *
1945    * @param key
1946    *          A key string.
1947    * @param value
1948    *          A Collection value.
1949    * @return this.
1950    * @throws JSONException
1951    *           If the value is non-finite number.
1952    * @throws NullPointerException
1953    *           If the key is <code>null</code>.
1954    */
1955   public JSONObject put(String key, Collection<?> value)
1956           throws JSONException
1957   {
1958     return this.put(key, new JSONArray(value));
1959   }
1960
1961   /**
1962    * Put a key/double pair in the JSONObject.
1963    *
1964    * @param key
1965    *          A key string.
1966    * @param value
1967    *          A double which is the value.
1968    * @return this.
1969    * @throws JSONException
1970    *           If the value is non-finite number.
1971    * @throws NullPointerException
1972    *           If the key is <code>null</code>.
1973    */
1974   public JSONObject put(String key, double value) throws JSONException
1975   {
1976     return this.put(key, Double.valueOf(value));
1977   }
1978
1979   /**
1980    * Put a key/float pair in the JSONObject.
1981    *
1982    * @param key
1983    *          A key string.
1984    * @param value
1985    *          A float which is the value.
1986    * @return this.
1987    * @throws JSONException
1988    *           If the value is non-finite number.
1989    * @throws NullPointerException
1990    *           If the key is <code>null</code>.
1991    */
1992   public JSONObject put(String key, float value) throws JSONException
1993   {
1994     return this.put(key, Float.valueOf(value));
1995   }
1996
1997   /**
1998    * Put a key/int pair in the JSONObject.
1999    *
2000    * @param key
2001    *          A key string.
2002    * @param value
2003    *          An int which is the value.
2004    * @return this.
2005    * @throws JSONException
2006    *           If the value is non-finite number.
2007    * @throws NullPointerException
2008    *           If the key is <code>null</code>.
2009    */
2010   public JSONObject put(String key, int value) throws JSONException
2011   {
2012     return this.put(key, Integer.valueOf(value));
2013   }
2014
2015   /**
2016    * Put a key/long pair in the JSONObject.
2017    *
2018    * @param key
2019    *          A key string.
2020    * @param value
2021    *          A long which is the value.
2022    * @return this.
2023    * @throws JSONException
2024    *           If the value is non-finite number.
2025    * @throws NullPointerException
2026    *           If the key is <code>null</code>.
2027    */
2028   public JSONObject put(String key, long value) throws JSONException
2029   {
2030     return this.put(key, Long.valueOf(value));
2031   }
2032
2033   /**
2034    * Put a key/value pair in the JSONObject, where the value will be a
2035    * JSONObject which is produced from a Map.
2036    *
2037    * @param key
2038    *          A key string.
2039    * @param value
2040    *          A Map value.
2041    * @return this.
2042    * @throws JSONException
2043    *           If the value is non-finite number.
2044    * @throws NullPointerException
2045    *           If the key is <code>null</code>.
2046    */
2047   public JSONObject put(String key, Map<?, ?> value) throws JSONException
2048   {
2049     return this.put(key, new JSONObject(value));
2050   }
2051
2052   /**
2053    * Put a key/value pair in the JSONObject. If the value is <code>null</code>,
2054    * then the key will be removed from the JSONObject if it is present.
2055    *
2056    * @param key
2057    *          A key string.
2058    * @param value
2059    *          An object which is the value. It should be of one of these types:
2060    *          Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or
2061    *          the JSONObject.NULL object.
2062    * @return this.
2063    * @throws JSONException
2064    *           If the value is non-finite number.
2065    * @throws NullPointerException
2066    *           If the key is <code>null</code>.
2067    */
2068   public JSONObject put(String key, Object value) throws JSONException
2069   {
2070     if (key == null)
2071     {
2072       throw new NullPointerException("Null key.");
2073     }
2074     if (value != null)
2075     {
2076       testValidity(value);
2077       this.map.put(key, value);
2078     }
2079     else
2080     {
2081       this.remove(key);
2082     }
2083     return this;
2084   }
2085
2086   /**
2087    * Put a key/value pair in the JSONObject, but only if the key and the value
2088    * are both non-null, and only if there is not already a member with that
2089    * name.
2090    *
2091    * @param key
2092    *          string
2093    * @param value
2094    *          object
2095    * @return this.
2096    * @throws JSONException
2097    *           if the key is a duplicate
2098    */
2099   public JSONObject putOnce(String key, Object value) throws JSONException
2100   {
2101     if (key != null && value != null)
2102     {
2103       if (this.opt(key) != null)
2104       {
2105         throw new JSONException("Duplicate key \"" + key + "\"");
2106       }
2107       return this.put(key, value);
2108     }
2109     return this;
2110   }
2111
2112   /**
2113    * Put a key/value pair in the JSONObject, but only if the key and the value
2114    * are both non-null.
2115    *
2116    * @param key
2117    *          A key string.
2118    * @param value
2119    *          An object which is the value. It should be of one of these types:
2120    *          Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or
2121    *          the JSONObject.NULL object.
2122    * @return this.
2123    * @throws JSONException
2124    *           If the value is a non-finite number.
2125    */
2126   public JSONObject putOpt(String key, Object value) throws JSONException
2127   {
2128     if (key != null && value != null)
2129     {
2130       return this.put(key, value);
2131     }
2132     return this;
2133   }
2134
2135   /**
2136    * Creates a JSONPointer using an initialization string and tries to match it
2137    * to an item within this JSONObject. For example, given a JSONObject
2138    * initialized with this document:
2139    * 
2140    * <pre>
2141    * {
2142    *     "a":{"b":"c"}
2143    * }
2144    * </pre>
2145    * 
2146    * and this JSONPointer string:
2147    * 
2148    * <pre>
2149    * "/a/b"
2150    * </pre>
2151    * 
2152    * Then this method will return the String "c". A JSONPointerException may be
2153    * thrown from code called by this method.
2154    * 
2155    * @param jsonPointer
2156    *          string that can be used to create a JSONPointer
2157    * @return the item matched by the JSONPointer, otherwise null
2158    */
2159   public Object query(String jsonPointer)
2160   {
2161     return query(new JSONPointer(jsonPointer));
2162   }
2163
2164   /**
2165    * Uses a user initialized JSONPointer and tries to match it to an item within
2166    * this JSONObject. For example, given a JSONObject initialized with this
2167    * document:
2168    * 
2169    * <pre>
2170    * {
2171    *     "a":{"b":"c"}
2172    * }
2173    * </pre>
2174    * 
2175    * and this JSONPointer:
2176    * 
2177    * <pre>
2178    * "/a/b"
2179    * </pre>
2180    * 
2181    * Then this method will return the String "c". A JSONPointerException may be
2182    * thrown from code called by this method.
2183    * 
2184    * @param jsonPointer
2185    *          string that can be used to create a JSONPointer
2186    * @return the item matched by the JSONPointer, otherwise null
2187    */
2188   public Object query(JSONPointer jsonPointer)
2189   {
2190     return jsonPointer.queryFrom(this);
2191   }
2192
2193   /**
2194    * Queries and returns a value from this object using {@code jsonPointer}, or
2195    * returns null if the query fails due to a missing key.
2196    * 
2197    * @param jsonPointer
2198    *          the string representation of the JSON pointer
2199    * @return the queried value or {@code null}
2200    * @throws IllegalArgumentException
2201    *           if {@code jsonPointer} has invalid syntax
2202    */
2203   public Object optQuery(String jsonPointer)
2204   {
2205     return optQuery(new JSONPointer(jsonPointer));
2206   }
2207
2208   /**
2209    * Queries and returns a value from this object using {@code jsonPointer}, or
2210    * returns null if the query fails due to a missing key.
2211    * 
2212    * @param jsonPointer
2213    *          The JSON pointer
2214    * @return the queried value or {@code null}
2215    * @throws IllegalArgumentException
2216    *           if {@code jsonPointer} has invalid syntax
2217    */
2218   public Object optQuery(JSONPointer jsonPointer)
2219   {
2220     try
2221     {
2222       return jsonPointer.queryFrom(this);
2223     } catch (JSONPointerException e)
2224     {
2225       return null;
2226     }
2227   }
2228
2229   /**
2230    * Produce a string in double quotes with backslash sequences in all the right
2231    * places. A backslash will be inserted within </, producing <\/, allowing
2232    * JSON text to be delivered in HTML. In JSON text, a string cannot contain a
2233    * control character or an unescaped quote or backslash.
2234    *
2235    * @param string
2236    *          A String
2237    * @return A String correctly formatted for insertion in a JSON text.
2238    */
2239   public static String quote(String string)
2240   {
2241     StringWriter sw = new StringWriter();
2242     synchronized (sw.getBuffer())
2243     {
2244       try
2245       {
2246         return quote(string, sw).toString();
2247       } catch (IOException ignored)
2248       {
2249         // will never happen - we are writing to a string writer
2250         return "";
2251       }
2252     }
2253   }
2254
2255   public static Writer quote(String string, Writer w) throws IOException
2256   {
2257     if (string == null || string.isEmpty())
2258     {
2259       w.write("\"\"");
2260       return w;
2261     }
2262
2263     char b;
2264     char c = 0;
2265     String hhhh;
2266     int i;
2267     int len = string.length();
2268
2269     w.write('"');
2270     for (i = 0; i < len; i += 1)
2271     {
2272       b = c;
2273       c = string.charAt(i);
2274       switch (c)
2275       {
2276       case '\\':
2277       case '"':
2278         w.write('\\');
2279         w.write(c);
2280         break;
2281       case '/':
2282         if (b == '<')
2283         {
2284           w.write('\\');
2285         }
2286         w.write(c);
2287         break;
2288       case '\b':
2289         w.write("\\b");
2290         break;
2291       case '\t':
2292         w.write("\\t");
2293         break;
2294       case '\n':
2295         w.write("\\n");
2296         break;
2297       case '\f':
2298         w.write("\\f");
2299         break;
2300       case '\r':
2301         w.write("\\r");
2302         break;
2303       default:
2304         if (c < ' ' || (c >= '\u0080' && c < '\u00a0')
2305                 || (c >= '\u2000' && c < '\u2100'))
2306         {
2307           w.write("\\u");
2308           hhhh = Integer.toHexString(c);
2309           w.write("0000", 0, 4 - hhhh.length());
2310           w.write(hhhh);
2311         }
2312         else
2313         {
2314           w.write(c);
2315         }
2316       }
2317     }
2318     w.write('"');
2319     return w;
2320   }
2321
2322   /**
2323    * Remove a name and its value, if present.
2324    *
2325    * @param key
2326    *          The name to be removed.
2327    * @return The value that was associated with the name, or null if there was
2328    *         no value.
2329    */
2330   public Object remove(String key)
2331   {
2332     return this.map.remove(key);
2333   }
2334
2335   /**
2336    * Determine if two JSONObjects are similar. They must contain the same set of
2337    * names which must be associated with similar values.
2338    *
2339    * @param other
2340    *          The other JSONObject
2341    * @return true if they are equal
2342    */
2343   public boolean similar(Object other)
2344   {
2345     try
2346     {
2347       if (!(other instanceof JSONObject))
2348       {
2349         return false;
2350       }
2351       if (!this.keySet().equals(((JSONObject) other).keySet()))
2352       {
2353         return false;
2354       }
2355       for (final Entry<String, ?> entry : this.entrySet())
2356       {
2357         String name = entry.getKey();
2358         Object valueThis = entry.getValue();
2359         Object valueOther = ((JSONObject) other).get(name);
2360         if (valueThis == valueOther)
2361         {
2362           continue;
2363         }
2364         if (valueThis == null)
2365         {
2366           return false;
2367         }
2368         if (valueThis instanceof JSONObject)
2369         {
2370           if (!((JSONObject) valueThis).similar(valueOther))
2371           {
2372             return false;
2373           }
2374         }
2375         else if (valueThis instanceof JSONArray)
2376         {
2377           if (!((JSONArray) valueThis).similar(valueOther))
2378           {
2379             return false;
2380           }
2381         }
2382         else if (!valueThis.equals(valueOther))
2383         {
2384           return false;
2385         }
2386       }
2387       return true;
2388     } catch (Throwable exception)
2389     {
2390       return false;
2391     }
2392   }
2393
2394   /**
2395    * Tests if the value should be tried as a decimal. It makes no test if there
2396    * are actual digits.
2397    * 
2398    * @param val
2399    *          value to test
2400    * @return true if the string is "-0" or if it contains '.', 'e', or 'E',
2401    *         false otherwise.
2402    */
2403   protected static boolean isDecimalNotation(final String val)
2404   {
2405     return val.indexOf('.') > -1 || val.indexOf('e') > -1
2406             || val.indexOf('E') > -1 || "-0".equals(val);
2407   }
2408
2409   /**
2410    * Converts a string to a number using the narrowest possible type. Possible
2411    * returns for this function are BigDecimal, Double, BigInteger, Long, and
2412    * Integer. When a Double is returned, it should always be a valid Double and
2413    * not NaN or +-infinity.
2414    * 
2415    * @param val
2416    *          value to convert
2417    * @return Number representation of the value.
2418    * @throws NumberFormatException
2419    *           thrown if the value is not a valid number. A public caller should
2420    *           catch this and wrap it in a {@link JSONException} if applicable.
2421    */
2422   protected static Number stringToNumber(final String val)
2423           throws NumberFormatException
2424   {
2425     char initial = val.charAt(0);
2426     if ((initial >= '0' && initial <= '9') || initial == '-')
2427     {
2428       // decimal representation
2429       if (isDecimalNotation(val))
2430       {
2431         // quick dirty way to see if we need a BigDecimal instead of a Double
2432         // this only handles some cases of overflow or underflow
2433         if (val.length() > 14)
2434         {
2435           return new BigDecimal(val);
2436         }
2437         final Double d = Double.valueOf(val);
2438         if (d.isInfinite() || d.isNaN())
2439         {
2440           // if we can't parse it as a double, go up to BigDecimal
2441           // this is probably due to underflow like 4.32e-678
2442           // or overflow like 4.65e5324. The size of the string is small
2443           // but can't be held in a Double.
2444           return new BigDecimal(val);
2445         }
2446         return d;
2447       }
2448       // integer representation.
2449       // This will narrow any values to the smallest reasonable Object
2450       // representation
2451       // (Integer, Long, or BigInteger)
2452
2453       // string version
2454       // The compare string length method reduces GC,
2455       // but leads to smaller integers being placed in larger wrappers even
2456       // though not
2457       // needed. i.e. 1,000,000,000 -> Long even though it's an Integer
2458       // 1,000,000,000,000,000,000 -> BigInteger even though it's a Long
2459       // if(val.length()<=9){
2460       // return Integer.valueOf(val);
2461       // }
2462       // if(val.length()<=18){
2463       // return Long.valueOf(val);
2464       // }
2465       // return new BigInteger(val);
2466
2467       // BigInteger version: We use a similar bitLenth compare as
2468       // BigInteger#intValueExact uses. Increases GC, but objects hold
2469       // only what they need. i.e. Less runtime overhead if the value is
2470       // long lived. Which is the better tradeoff? This is closer to what's
2471       // in stringToValue.
2472       BigInteger bi = new BigInteger(val);
2473       if (bi.bitLength() <= 31)
2474       {
2475         return Integer.valueOf(bi.intValue());
2476       }
2477       if (bi.bitLength() <= 63)
2478       {
2479         return Long.valueOf(bi.longValue());
2480       }
2481       return bi;
2482     }
2483     throw new NumberFormatException(
2484             "val [" + val + "] is not a valid number.");
2485   }
2486
2487   /**
2488    * Try to convert a string into a number, boolean, or null. If the string
2489    * can't be converted, return the string.
2490    *
2491    * @param string
2492    *          A String.
2493    * @return A simple JSON value.
2494    */
2495   // Changes to this method must be copied to the corresponding method in
2496   // the XML class to keep full support for Android
2497   public static Object stringToValue(String string)
2498   {
2499     if (string.equals(""))
2500     {
2501       return string;
2502     }
2503     if (string.equalsIgnoreCase("true"))
2504     {
2505       return Boolean.TRUE;
2506     }
2507     if (string.equalsIgnoreCase("false"))
2508     {
2509       return Boolean.FALSE;
2510     }
2511     if (string.equalsIgnoreCase("null"))
2512     {
2513       return JSONObject.NULL;
2514     }
2515
2516     /*
2517      * If it might be a number, try converting it. If a number cannot be produced,
2518      * then the value will just be a string.
2519      */
2520
2521     char initial = string.charAt(0);
2522     if ((initial >= '0' && initial <= '9') || initial == '-')
2523     {
2524       try
2525       {
2526         // if we want full Big Number support this block can be replaced with:
2527         // return stringToNumber(string);
2528         if (isDecimalNotation(string))
2529         {
2530           Double d = Double.valueOf(string);
2531           if (!d.isInfinite() && !d.isNaN())
2532           {
2533             return d;
2534           }
2535         }
2536         else
2537         {
2538           Long myLong = Long.valueOf(string);
2539           if (string.equals(myLong.toString()))
2540           {
2541             if (myLong.longValue() == myLong.intValue())
2542             {
2543               return Integer.valueOf(myLong.intValue());
2544             }
2545             return myLong;
2546           }
2547         }
2548       } catch (Exception ignore)
2549       {
2550       }
2551     }
2552     return string;
2553   }
2554
2555   /**
2556    * Throw an exception if the object is a NaN or infinite number.
2557    *
2558    * @param o
2559    *          The object to test.
2560    * @throws JSONException
2561    *           If o is a non-finite number.
2562    */
2563   public static void testValidity(Object o) throws JSONException
2564   {
2565     if (o != null)
2566     {
2567       if (o instanceof Double)
2568       {
2569         if (((Double) o).isInfinite() || ((Double) o).isNaN())
2570         {
2571           throw new JSONException(
2572                   "JSON does not allow non-finite numbers.");
2573         }
2574       }
2575       else if (o instanceof Float)
2576       {
2577         if (((Float) o).isInfinite() || ((Float) o).isNaN())
2578         {
2579           throw new JSONException(
2580                   "JSON does not allow non-finite numbers.");
2581         }
2582       }
2583     }
2584   }
2585
2586   /**
2587    * Produce a JSONArray containing the values of the members of this
2588    * JSONObject.
2589    *
2590    * @param names
2591    *          A JSONArray containing a list of key strings. This determines the
2592    *          sequence of the values in the result.
2593    * @return A JSONArray of values.
2594    * @throws JSONException
2595    *           If any of the values are non-finite numbers.
2596    */
2597   public JSONArray toJSONArray(JSONArray names) throws JSONException
2598   {
2599     if (names == null || names.isEmpty())
2600     {
2601       return null;
2602     }
2603     JSONArray ja = new JSONArray();
2604     for (int i = 0; i < names.length(); i += 1)
2605     {
2606       ja.put(this.opt(names.getString(i)));
2607     }
2608     return ja;
2609   }
2610
2611   /**
2612    * Make a JSON text of this JSONObject. For compactness, no whitespace is
2613    * added. If this would not result in a syntactically correct JSON text, then
2614    * null will be returned instead.
2615    * <p>
2616    * <b> Warning: This method assumes that the data structure is acyclical. </b>
2617    * 
2618    * @return a printable, displayable, portable, transmittable representation of
2619    *         the object, beginning with <code>{</code>&nbsp;<small>(left
2620    *         brace)</small> and ending with <code>}</code>&nbsp;<small>(right
2621    *         brace)</small>.
2622    */
2623   @Override
2624   public String toString()
2625   {
2626     try
2627     {
2628       return this.toString(0);
2629     } catch (Exception e)
2630     {
2631       return null;
2632     }
2633   }
2634
2635   /**
2636    * Make a pretty-printed JSON text of this JSONObject.
2637    * 
2638    * <p>
2639    * If <code>indentFactor > 0</code> and the {@link JSONObject} has only one
2640    * key, then the object will be output on a single line:
2641    * 
2642    * <pre>
2643    * {@code {"key": 1}}
2644    * </pre>
2645    * 
2646    * <p>
2647    * If an object has 2 or more keys, then it will be output across multiple
2648    * lines: <code><pre>{
2649    *  "key1": 1,
2650    *  "key2": "value 2",
2651    *  "key3": 3
2652    * }</pre></code>
2653    * <p>
2654    * <b> Warning: This method assumes that the data structure is acyclical. </b>
2655    *
2656    * @param indentFactor
2657    *          The number of spaces to add to each level of indentation.
2658    * @return a printable, displayable, portable, transmittable representation of
2659    *         the object, beginning with <code>{</code>&nbsp;<small>(left
2660    *         brace)</small> and ending with <code>}</code>&nbsp;<small>(right
2661    *         brace)</small>.
2662    * @throws JSONException
2663    *           If the object contains an invalid number.
2664    */
2665   public String toString(int indentFactor) throws JSONException
2666   {
2667     StringWriter w = new StringWriter();
2668     synchronized (w.getBuffer())
2669     {
2670       return this.write(w, indentFactor, 0).toString();
2671     }
2672   }
2673
2674   /**
2675    * Make a JSON text of an Object value. If the object has an
2676    * value.toJSONString() method, then that method will be used to produce the
2677    * JSON text. The method is required to produce a strictly conforming text. If
2678    * the object does not contain a toJSONString method (which is the most common
2679    * case), then a text will be produced by other means. If the value is an
2680    * array or Collection, then a JSONArray will be made from it and its
2681    * toJSONString method will be called. If the value is a MAP, then a
2682    * JSONObject will be made from it and its toJSONString method will be called.
2683    * Otherwise, the value's toString method will be called, and the result will
2684    * be quoted.
2685    *
2686    * <p>
2687    * Warning: This method assumes that the data structure is acyclical.
2688    *
2689    * @param value
2690    *          The value to be serialized.
2691    * @return a printable, displayable, transmittable representation of the
2692    *         object, beginning with <code>{</code>&nbsp;<small>(left
2693    *         brace)</small> and ending with <code>}</code>&nbsp;<small>(right
2694    *         brace)</small>.
2695    * @throws JSONException
2696    *           If the value is or contains an invalid number.
2697    */
2698   public static String valueToString(Object value) throws JSONException
2699   {
2700     // moves the implementation to JSONWriter as:
2701     // 1. It makes more sense to be part of the writer class
2702     // 2. For Android support this method is not available. By implementing it
2703     // in
2704     // the Writer
2705     // Android users can use the writer with the built in Android JSONObject
2706     // implementation.
2707     return JSONWriter.valueToString(value);
2708   }
2709
2710   /**
2711    * Wrap an object, if necessary. If the object is <code>null</code>, return
2712    * the NULL object. If it is an array or collection, wrap it in a JSONArray.
2713    * If it is a map, wrap it in a JSONObject. If it is a standard property
2714    * (Double, String, et al) then it is already wrapped. Otherwise, if it comes
2715    * from one of the java packages, turn it into a string. And if it doesn't,
2716    * try to wrap it in a JSONObject. If the wrapping fails, then null is
2717    * returned.
2718    *
2719    * @param object
2720    *          The object to wrap
2721    * @return The wrapped value
2722    */
2723   public static Object wrap(Object object)
2724   {
2725     try
2726     {
2727       if (object == null)
2728       {
2729         return NULL;
2730       }
2731       if (object instanceof JSONObject || object instanceof JSONArray
2732               || NULL.equals(object) || object instanceof JSONString
2733               || object instanceof Byte || object instanceof Character
2734               || object instanceof Short || object instanceof Integer
2735               || object instanceof Long || object instanceof Boolean
2736               || object instanceof Float || object instanceof Double
2737               || object instanceof String || object instanceof BigInteger
2738               || object instanceof BigDecimal || object instanceof Enum)
2739       {
2740         return object;
2741       }
2742
2743       if (object instanceof Collection)
2744       {
2745         Collection<?> coll = (Collection<?>) object;
2746         return new JSONArray(coll);
2747       }
2748       if (object.getClass().isArray())
2749       {
2750         return new JSONArray(object);
2751       }
2752       if (object instanceof Map)
2753       {
2754         Map<?, ?> map = (Map<?, ?>) object;
2755         return new JSONObject(map);
2756       }
2757       Package objectPackage = object.getClass().getPackage();
2758       String objectPackageName = objectPackage != null
2759               ? objectPackage.getName()
2760               : "";
2761       if (objectPackageName.startsWith("java.")
2762               || objectPackageName.startsWith("javax.")
2763               || object.getClass().getClassLoader() == null)
2764       {
2765         return object.toString();
2766       }
2767       return new JSONObject(object);
2768     } catch (Exception exception)
2769     {
2770       return null;
2771     }
2772   }
2773
2774   /**
2775    * Write the contents of the JSONObject as JSON text to a writer. For
2776    * compactness, no whitespace is added.
2777    * <p>
2778    * <b> Warning: This method assumes that the data structure is acyclical. </b>
2779    * 
2780    * @return The writer.
2781    * @throws JSONException
2782    */
2783   public Writer write(Writer writer) throws JSONException
2784   {
2785     return this.write(writer, 0, 0);
2786   }
2787
2788   static final Writer writeValue(Writer writer, Object value,
2789           int indentFactor, int indent) throws JSONException, IOException
2790   {
2791     if (value == null || value.equals(null))
2792     {
2793       writer.write("null");
2794     }
2795     else if (value instanceof JSONString)
2796     {
2797       Object o;
2798       try
2799       {
2800         o = ((JSONString) value).toJSONString();
2801       } catch (Exception e)
2802       {
2803         throw new JSONException(e);
2804       }
2805       writer.write(o != null ? o.toString() : quote(value.toString()));
2806     }
2807     else if (value instanceof Number)
2808     {
2809       // not all Numbers may match actual JSON Numbers. i.e. fractions or
2810       // Imaginary
2811       final String numberAsString = numberToString((Number) value);
2812       try
2813       {
2814         // Use the BigDecimal constructor for its parser to validate the format.
2815         @SuppressWarnings("unused")
2816         BigDecimal testNum = new BigDecimal(numberAsString);
2817         // Close enough to a JSON number that we will use it unquoted
2818         writer.write(numberAsString);
2819       } catch (NumberFormatException ex)
2820       {
2821         // The Number value is not a valid JSON number.
2822         // Instead we will quote it as a string
2823         quote(numberAsString, writer);
2824       }
2825     }
2826     else if (value instanceof Boolean)
2827     {
2828       writer.write(value.toString());
2829     }
2830     else if (value instanceof Enum<?>)
2831     {
2832       writer.write(quote(((Enum<?>) value).name()));
2833     }
2834     else if (value instanceof JSONObject)
2835     {
2836       ((JSONObject) value).write(writer, indentFactor, indent);
2837     }
2838     else if (value instanceof JSONArray)
2839     {
2840       ((JSONArray) value).write(writer, indentFactor, indent);
2841     }
2842     else if (value instanceof Map)
2843     {
2844       Map<?, ?> map = (Map<?, ?>) value;
2845       new JSONObject(map).write(writer, indentFactor, indent);
2846     }
2847     else if (value instanceof Collection)
2848     {
2849       Collection<?> coll = (Collection<?>) value;
2850       new JSONArray(coll).write(writer, indentFactor, indent);
2851     }
2852     else if (value.getClass().isArray())
2853     {
2854       new JSONArray(value).write(writer, indentFactor, indent);
2855     }
2856     else
2857     {
2858       quote(value.toString(), writer);
2859     }
2860     return writer;
2861   }
2862
2863   static final void indent(Writer writer, int indent) throws IOException
2864   {
2865     for (int i = 0; i < indent; i += 1)
2866     {
2867       writer.write(' ');
2868     }
2869   }
2870
2871   /**
2872    * Write the contents of the JSONObject as JSON text to a writer.
2873    * 
2874    * <p>
2875    * If <code>indentFactor > 0</code> and the {@link JSONObject} has only one
2876    * key, then the object will be output on a single line:
2877    * 
2878    * <pre>
2879    * {@code {"key": 1}}
2880    * </pre>
2881    * 
2882    * <p>
2883    * If an object has 2 or more keys, then it will be output across multiple
2884    * lines: <code><pre>{
2885    *  "key1": 1,
2886    *  "key2": "value 2",
2887    *  "key3": 3
2888    * }</pre></code>
2889    * <p>
2890    * <b> Warning: This method assumes that the data structure is acyclical. </b>
2891    *
2892    * @param writer
2893    *          Writes the serialized JSON
2894    * @param indentFactor
2895    *          The number of spaces to add to each level of indentation.
2896    * @param indent
2897    *          The indentation of the top level.
2898    * @return The writer.
2899    * @throws JSONException
2900    */
2901   public Writer write(Writer writer, int indentFactor, int indent)
2902           throws JSONException
2903   {
2904     try
2905     {
2906       boolean commanate = false;
2907       final int length = this.length();
2908       writer.write('{');
2909
2910       if (length == 1)
2911       {
2912         final Entry<String, ?> entry = this.entrySet().iterator().next();
2913         final String key = entry.getKey();
2914         writer.write(quote(key));
2915         writer.write(':');
2916         if (indentFactor > 0)
2917         {
2918           writer.write(' ');
2919         }
2920         try
2921         {
2922           writeValue(writer, entry.getValue(), indentFactor, indent);
2923         } catch (Exception e)
2924         {
2925           throw new JSONException(
2926                   "Unable to write JSONObject value for key: " + key, e);
2927         }
2928       }
2929       else if (length != 0)
2930       {
2931         final int newindent = indent + indentFactor;
2932         for (final Entry<String, ?> entry : this.entrySet())
2933         {
2934           if (commanate)
2935           {
2936             writer.write(',');
2937           }
2938           if (indentFactor > 0)
2939           {
2940             writer.write('\n');
2941           }
2942           indent(writer, newindent);
2943           final String key = entry.getKey();
2944           writer.write(quote(key));
2945           writer.write(':');
2946           if (indentFactor > 0)
2947           {
2948             writer.write(' ');
2949           }
2950           try
2951           {
2952             writeValue(writer, entry.getValue(), indentFactor, newindent);
2953           } catch (Exception e)
2954           {
2955             throw new JSONException(
2956                     "Unable to write JSONObject value for key: " + key, e);
2957           }
2958           commanate = true;
2959         }
2960         if (indentFactor > 0)
2961         {
2962           writer.write('\n');
2963         }
2964         indent(writer, indent);
2965       }
2966       writer.write('}');
2967       return writer;
2968     } catch (IOException exception)
2969     {
2970       throw new JSONException(exception);
2971     }
2972   }
2973
2974   /**
2975    * Returns a java.util.Map containing all of the entries in this object. If an
2976    * entry in the object is a JSONArray or JSONObject it will also be converted.
2977    * <p>
2978    * Warning: This method assumes that the data structure is acyclical.
2979    *
2980    * @return a java.util.Map containing the entries of this object
2981    */
2982   public Map<String, Object> toMap()
2983   {
2984     Map<String, Object> results = new HashMap<String, Object>();
2985     for (Entry<String, Object> entry : this.entrySet())
2986     {
2987       Object value;
2988       if (entry.getValue() == null || NULL.equals(entry.getValue()))
2989       {
2990         value = null;
2991       }
2992       else if (entry.getValue() instanceof JSONObject)
2993       {
2994         value = ((JSONObject) entry.getValue()).toMap();
2995       }
2996       else if (entry.getValue() instanceof JSONArray)
2997       {
2998         value = ((JSONArray) entry.getValue()).toList();
2999       }
3000       else
3001       {
3002         value = entry.getValue();
3003       }
3004       results.put(entry.getKey(), value);
3005     }
3006     return results;
3007   }
3008 }