~dhis-mobile-devs/dhis-mobile/2.16

« back to all changes in this revision

Viewing changes to src/org/json/me/JSONObject.java

  • Committer: paulmarkcastillo at gmail
  • Date: 2014-06-13 05:45:01 UTC
  • Revision ID: paulmarkcastillo@gmail.com-20140613054501-w3d3y0nvkznyi5t1
Added logs, and organized imports.

Show diffs side-by-side

added added

removed removed

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