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