001: package org.jboss.portal.widget.netvibes.json;
002:
003: /*
004: Copyright (c) 2002 JSON.org
005:
006: Permission is hereby granted, free of charge, to any person obtaining a copy
007: of this software and associated documentation files (the "Software"), to deal
008: in the Software without restriction, including without limitation the rights
009: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010: copies of the Software, and to permit persons to whom the Software is
011: furnished to do so, subject to the following conditions:
012:
013: The above copyright notice and this permission notice shall be included in all
014: copies or substantial portions of the Software.
015:
016: The Software shall be used for Good, not Evil.
017:
018: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
019: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
020: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
021: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
022: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
023: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
024: SOFTWARE.
025: */
026:
027: import java.io.IOException;
028: import java.io.Writer;
029: import java.lang.reflect.Array;
030: import java.util.ArrayList;
031: import java.util.Collection;
032: import java.util.Map;
033:
034: /**
035: * A JSONArray is an ordered sequence of values. Its external text form is a
036: * string wrapped in square brackets with commas separating the values. The
037: * internal form is an object having <code>get</code> and <code>opt</code>
038: * methods for accessing the values by index, and <code>put</code> methods for
039: * adding or replacing values. The values can be any of these types:
040: * <code>Boolean</code>, <code>JSONArray</code>, <code>JSONObject</code>,
041: * <code>Number</code>, <code>String</code>, or the
042: * <code>JSONObject.NULL object</code>.
043: * <p>
044: * The constructor can convert a JSON text into a Java object. The
045: * <code>toString</code> method converts to JSON text.
046: * <p>
047: * A <code>get</code> method returns a value if one can be found, and throws an
048: * exception if one cannot be found. An <code>opt</code> method returns a
049: * default value instead of throwing an exception, and so is useful for
050: * obtaining optional values.
051: * <p>
052: * The generic <code>get()</code> and <code>opt()</code> methods return an
053: * object which you can cast or query for type. There are also typed
054: * <code>get</code> and <code>opt</code> methods that do type checking and type
055: * coersion for you.
056: * <p>
057: * The texts produced by the <code>toString</code> methods strictly conform to
058: * JSON syntax rules. The constructors are more forgiving in the texts they will
059: * accept:
060: * <ul>
061: * <li>An extra <code>,</code> <small>(comma)</small> may appear just
062: * before the closing bracket.</li>
063: * <li>The <code>null</code> value will be inserted when there
064: * is <code>,</code> <small>(comma)</small> elision.</li>
065: * <li>Strings may be quoted with <code>'</code> <small>(single
066: * quote)</small>.</li>
067: * <li>Strings do not need to be quoted at all if they do not begin with a quote
068: * or single quote, and if they do not contain leading or trailing spaces,
069: * and if they do not contain any of these characters:
070: * <code>{ } [ ] / \ : , = ; #</code> and if they do not look like numbers
071: * and if they are not the reserved words <code>true</code>,
072: * <code>false</code>, or <code>null</code>.</li>
073: * <li>Values can be separated by <code>;</code> <small>(semicolon)</small> as
074: * well as by <code>,</code> <small>(comma)</small>.</li>
075: * <li>Numbers may have the <code>0-</code> <small>(octal)</small> or
076: * <code>0x-</code> <small>(hex)</small> prefix.</li>
077: * <li>Comments written in the slashshlash, slashstar, and hash conventions
078: * will be ignored.</li>
079: * </ul>
080:
081: * @author JSON.org
082: * @version 2
083: */
084: public class JSONArray {
085:
086: /**
087: * The arrayList where the JSONArray's properties are kept.
088: */
089: private ArrayList myArrayList;
090:
091: /**
092: * Construct an empty JSONArray.
093: */
094: public JSONArray() {
095: this .myArrayList = new ArrayList();
096: }
097:
098: /**
099: * Construct a JSONArray from a JSONTokener.
100: * @param x A JSONTokener
101: * @throws JSONException If there is a syntax error.
102: */
103: public JSONArray(JSONTokener x) throws JSONException {
104: this ();
105: if (x.nextClean() != '[') {
106: throw x.syntaxError("A JSONArray text must start with '['");
107: }
108: if (x.nextClean() == ']') {
109: return;
110: }
111: x.back();
112: for (;;) {
113: if (x.nextClean() == ',') {
114: x.back();
115: this .myArrayList.add(null);
116: } else {
117: x.back();
118: this .myArrayList.add(x.nextValue());
119: }
120: switch (x.nextClean()) {
121: case ';':
122: case ',':
123: if (x.nextClean() == ']') {
124: return;
125: }
126: x.back();
127: break;
128: case ']':
129: return;
130: default:
131: throw x.syntaxError("Expected a ',' or ']'");
132: }
133: }
134: }
135:
136: /**
137: * Construct a JSONArray from a source JSON text.
138: * @param source A string that begins with
139: * <code>[</code> <small>(left bracket)</small>
140: * and ends with <code>]</code> <small>(right bracket)</small>.
141: * @throws JSONException If there is a syntax error.
142: */
143: public JSONArray(String source) throws JSONException {
144: this (new JSONTokener(source));
145: }
146:
147: /**
148: * Construct a JSONArray from a Collection.
149: * @param collection A Collection.
150: */
151: public JSONArray(Collection collection) {
152: this .myArrayList = (collection == null) ? new ArrayList()
153: : new ArrayList(collection);
154: }
155:
156: /**
157: * Construct a JSONArray from an array
158: * @throws JSONException If not an array.
159: */
160: public JSONArray(Object array) throws JSONException {
161: this ();
162: if (array.getClass().isArray()) {
163: int length = Array.getLength(array);
164: for (int i = 0; i < length; i += 1) {
165: this .put(Array.get(array, i));
166: }
167: } else {
168: throw new JSONException(
169: "JSONArray initial value should be a string or collection or array.");
170: }
171: }
172:
173: /**
174: * Get the object value associated with an index.
175: * @param index
176: * The index must be between 0 and length() - 1.
177: * @return An object value.
178: * @throws JSONException If there is no value for the index.
179: */
180: public Object get(int index) throws JSONException {
181: Object o = opt(index);
182: if (o == null) {
183: throw new JSONException("JSONArray[" + index
184: + "] not found.");
185: }
186: return o;
187: }
188:
189: /**
190: * Get the boolean value associated with an index.
191: * The string values "true" and "false" are converted to boolean.
192: *
193: * @param index The index must be between 0 and length() - 1.
194: * @return The truth.
195: * @throws JSONException If there is no value for the index or if the
196: * value is not convertable to boolean.
197: */
198: public boolean getBoolean(int index) throws JSONException {
199: Object o = get(index);
200: if (o.equals(Boolean.FALSE)
201: || (o instanceof String && ((String) o)
202: .equalsIgnoreCase("false"))) {
203: return false;
204: } else if (o.equals(Boolean.TRUE)
205: || (o instanceof String && ((String) o)
206: .equalsIgnoreCase("true"))) {
207: return true;
208: }
209: throw new JSONException("JSONArray[" + index
210: + "] is not a Boolean.");
211: }
212:
213: /**
214: * Get the double value associated with an index.
215: *
216: * @param index The index must be between 0 and length() - 1.
217: * @return The value.
218: * @throws JSONException If the key is not found or if the value cannot
219: * be converted to a number.
220: */
221: public double getDouble(int index) throws JSONException {
222: Object o = get(index);
223: try {
224: return o instanceof Number ? ((Number) o).doubleValue()
225: : Double.valueOf((String) o).doubleValue();
226: } catch (Exception e) {
227: throw new JSONException("JSONArray[" + index
228: + "] is not a number.");
229: }
230: }
231:
232: /**
233: * Get the int value associated with an index.
234: *
235: * @param index The index must be between 0 and length() - 1.
236: * @return The value.
237: * @throws JSONException If the key is not found or if the value cannot
238: * be converted to a number.
239: * if the value cannot be converted to a number.
240: */
241: public int getInt(int index) throws JSONException {
242: Object o = get(index);
243: return o instanceof Number ? ((Number) o).intValue()
244: : (int) getDouble(index);
245: }
246:
247: /**
248: * Get the JSONArray associated with an index.
249: * @param index The index must be between 0 and length() - 1.
250: * @return A JSONArray value.
251: * @throws JSONException If there is no value for the index. or if the
252: * value is not a JSONArray
253: */
254: public JSONArray getJSONArray(int index) throws JSONException {
255: Object o = get(index);
256: if (o instanceof JSONArray) {
257: return (JSONArray) o;
258: }
259: throw new JSONException("JSONArray[" + index
260: + "] is not a JSONArray.");
261: }
262:
263: /**
264: * Get the JSONObject associated with an index.
265: * @param index subscript
266: * @return A JSONObject value.
267: * @throws JSONException If there is no value for the index or if the
268: * value is not a JSONObject
269: */
270: public JSONObject getJSONObject(int index) throws JSONException {
271: Object o = get(index);
272: if (o instanceof JSONObject) {
273: return (JSONObject) o;
274: }
275: throw new JSONException("JSONArray[" + index
276: + "] is not a JSONObject.");
277: }
278:
279: /**
280: * Get the long value associated with an index.
281: *
282: * @param index The index must be between 0 and length() - 1.
283: * @return The value.
284: * @throws JSONException If the key is not found or if the value cannot
285: * be converted to a number.
286: */
287: public long getLong(int index) throws JSONException {
288: Object o = get(index);
289: return o instanceof Number ? ((Number) o).longValue()
290: : (long) getDouble(index);
291: }
292:
293: /**
294: * Get the string associated with an index.
295: * @param index The index must be between 0 and length() - 1.
296: * @return A string value.
297: * @throws JSONException If there is no value for the index.
298: */
299: public String getString(int index) throws JSONException {
300: return get(index).toString();
301: }
302:
303: /**
304: * Determine if the value is null.
305: * @param index The index must be between 0 and length() - 1.
306: * @return true if the value at the index is null, or if there is no value.
307: */
308: public boolean isNull(int index) {
309: return JSONObject.NULL.equals(opt(index));
310: }
311:
312: /**
313: * Make a string from the contents of this JSONArray. The
314: * <code>separator</code> string is inserted between each element.
315: * Warning: This method assumes that the data structure is acyclical.
316: * @param separator A string that will be inserted between the elements.
317: * @return a string.
318: * @throws JSONException If the array contains an invalid number.
319: */
320: public String join(String separator) throws JSONException {
321: int len = length();
322: StringBuffer sb = new StringBuffer();
323:
324: for (int i = 0; i < len; i += 1) {
325: if (i > 0) {
326: sb.append(separator);
327: }
328: sb
329: .append(JSONObject.valueToString(this .myArrayList
330: .get(i)));
331: }
332: return sb.toString();
333: }
334:
335: /**
336: * Get the number of elements in the JSONArray, included nulls.
337: *
338: * @return The length (or size).
339: */
340: public int length() {
341: return this .myArrayList.size();
342: }
343:
344: /**
345: * Get the optional object value associated with an index.
346: * @param index The index must be between 0 and length() - 1.
347: * @return An object value, or null if there is no
348: * object at that index.
349: */
350: public Object opt(int index) {
351: return (index < 0 || index >= length()) ? null
352: : this .myArrayList.get(index);
353: }
354:
355: /**
356: * Get the optional boolean value associated with an index.
357: * It returns false if there is no value at that index,
358: * or if the value is not Boolean.TRUE or the String "true".
359: *
360: * @param index The index must be between 0 and length() - 1.
361: * @return The truth.
362: */
363: public boolean optBoolean(int index) {
364: return optBoolean(index, false);
365: }
366:
367: /**
368: * Get the optional boolean value associated with an index.
369: * It returns the defaultValue if there is no value at that index or if
370: * it is not a Boolean or the String "true" or "false" (case insensitive).
371: *
372: * @param index The index must be between 0 and length() - 1.
373: * @param defaultValue A boolean default.
374: * @return The truth.
375: */
376: public boolean optBoolean(int index, boolean defaultValue) {
377: try {
378: return getBoolean(index);
379: } catch (Exception e) {
380: return defaultValue;
381: }
382: }
383:
384: /**
385: * Get the optional double value associated with an index.
386: * NaN is returned if there is no value for the index,
387: * or if the value is not a number and cannot be converted to a number.
388: *
389: * @param index The index must be between 0 and length() - 1.
390: * @return The value.
391: */
392: public double optDouble(int index) {
393: return optDouble(index, Double.NaN);
394: }
395:
396: /**
397: * Get the optional double value associated with an index.
398: * The defaultValue is returned if there is no value for the index,
399: * or if the value is not a number and cannot be converted to a number.
400: *
401: * @param index subscript
402: * @param defaultValue The default value.
403: * @return The value.
404: */
405: public double optDouble(int index, double defaultValue) {
406: try {
407: return getDouble(index);
408: } catch (Exception e) {
409: return defaultValue;
410: }
411: }
412:
413: /**
414: * Get the optional int value associated with an index.
415: * Zero is returned if there is no value for the index,
416: * or if the value is not a number and cannot be converted to a number.
417: *
418: * @param index The index must be between 0 and length() - 1.
419: * @return The value.
420: */
421: public int optInt(int index) {
422: return optInt(index, 0);
423: }
424:
425: /**
426: * Get the optional int value associated with an index.
427: * The defaultValue is returned if there is no value for the index,
428: * or if the value is not a number and cannot be converted to a number.
429: * @param index The index must be between 0 and length() - 1.
430: * @param defaultValue The default value.
431: * @return The value.
432: */
433: public int optInt(int index, int defaultValue) {
434: try {
435: return getInt(index);
436: } catch (Exception e) {
437: return defaultValue;
438: }
439: }
440:
441: /**
442: * Get the optional JSONArray associated with an index.
443: * @param index subscript
444: * @return A JSONArray value, or null if the index has no value,
445: * or if the value is not a JSONArray.
446: */
447: public JSONArray optJSONArray(int index) {
448: Object o = opt(index);
449: return o instanceof JSONArray ? (JSONArray) o : null;
450: }
451:
452: /**
453: * Get the optional JSONObject associated with an index.
454: * Null is returned if the key is not found, or null if the index has
455: * no value, or if the value is not a JSONObject.
456: *
457: * @param index The index must be between 0 and length() - 1.
458: * @return A JSONObject value.
459: */
460: public JSONObject optJSONObject(int index) {
461: Object o = opt(index);
462: return o instanceof JSONObject ? (JSONObject) o : null;
463: }
464:
465: /**
466: * Get the optional long value associated with an index.
467: * Zero is returned if there is no value for the index,
468: * or if the value is not a number and cannot be converted to a number.
469: *
470: * @param index The index must be between 0 and length() - 1.
471: * @return The value.
472: */
473: public long optLong(int index) {
474: return optLong(index, 0);
475: }
476:
477: /**
478: * Get the optional long value associated with an index.
479: * The defaultValue is returned if there is no value for the index,
480: * or if the value is not a number and cannot be converted to a number.
481: * @param index The index must be between 0 and length() - 1.
482: * @param defaultValue The default value.
483: * @return The value.
484: */
485: public long optLong(int index, long defaultValue) {
486: try {
487: return getLong(index);
488: } catch (Exception e) {
489: return defaultValue;
490: }
491: }
492:
493: /**
494: * Get the optional string value associated with an index. It returns an
495: * empty string if there is no value at that index. If the value
496: * is not a string and is not null, then it is coverted to a string.
497: *
498: * @param index The index must be between 0 and length() - 1.
499: * @return A String value.
500: */
501: public String optString(int index) {
502: return optString(index, "");
503: }
504:
505: /**
506: * Get the optional string associated with an index.
507: * The defaultValue is returned if the key is not found.
508: *
509: * @param index The index must be between 0 and length() - 1.
510: * @param defaultValue The default value.
511: * @return A String value.
512: */
513: public String optString(int index, String defaultValue) {
514: Object o = opt(index);
515: return o != null ? o.toString() : defaultValue;
516: }
517:
518: /**
519: * Append a boolean value. This increases the array's length by one.
520: *
521: * @param value A boolean value.
522: * @return this.
523: */
524: public JSONArray put(boolean value) {
525: put(value ? Boolean.TRUE : Boolean.FALSE);
526: return this ;
527: }
528:
529: /**
530: * Put a value in the JSONArray, where the value will be a
531: * JSONArray which is produced from a Collection.
532: * @param value A Collection value.
533: * @return this.
534: */
535: public JSONArray put(Collection value) {
536: put(new JSONArray(value));
537: return this ;
538: }
539:
540: /**
541: * Append a double value. This increases the array's length by one.
542: *
543: * @param value A double value.
544: * @throws JSONException if the value is not finite.
545: * @return this.
546: */
547: public JSONArray put(double value) throws JSONException {
548: Double d = new Double(value);
549: JSONObject.testValidity(d);
550: put(d);
551: return this ;
552: }
553:
554: /**
555: * Append an int value. This increases the array's length by one.
556: *
557: * @param value An int value.
558: * @return this.
559: */
560: public JSONArray put(int value) {
561: put(new Integer(value));
562: return this ;
563: }
564:
565: /**
566: * Append an long value. This increases the array's length by one.
567: *
568: * @param value A long value.
569: * @return this.
570: */
571: public JSONArray put(long value) {
572: put(new Long(value));
573: return this ;
574: }
575:
576: /**
577: * Put a value in the JSONArray, where the value will be a
578: * JSONObject which is produced from a Map.
579: * @param value A Map value.
580: * @return this.
581: */
582: public JSONArray put(Map value) {
583: put(new JSONObject(value));
584: return this ;
585: }
586:
587: /**
588: * Append an object value. This increases the array's length by one.
589: * @param value An object value. The value should be a
590: * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the
591: * JSONObject.NULL object.
592: * @return this.
593: */
594: public JSONArray put(Object value) {
595: this .myArrayList.add(value);
596: return this ;
597: }
598:
599: /**
600: * Put or replace a boolean value in the JSONArray. If the index is greater
601: * than the length of the JSONArray, then null elements will be added as
602: * necessary to pad it out.
603: * @param index The subscript.
604: * @param value A boolean value.
605: * @return this.
606: * @throws JSONException If the index is negative.
607: */
608: public JSONArray put(int index, boolean value) throws JSONException {
609: put(index, value ? Boolean.TRUE : Boolean.FALSE);
610: return this ;
611: }
612:
613: /**
614: * Put a value in the JSONArray, where the value will be a
615: * JSONArray which is produced from a Collection.
616: * @param index The subscript.
617: * @param value A Collection value.
618: * @return this.
619: * @throws JSONException If the index is negative or if the value is
620: * not finite.
621: */
622: public JSONArray put(int index, Collection value)
623: throws JSONException {
624: put(index, new JSONArray(value));
625: return this ;
626: }
627:
628: /**
629: * Put or replace a double value. If the index is greater than the length of
630: * the JSONArray, then null elements will be added as necessary to pad
631: * it out.
632: * @param index The subscript.
633: * @param value A double value.
634: * @return this.
635: * @throws JSONException If the index is negative or if the value is
636: * not finite.
637: */
638: public JSONArray put(int index, double value) throws JSONException {
639: put(index, new Double(value));
640: return this ;
641: }
642:
643: /**
644: * Put or replace an int value. If the index is greater than the length of
645: * the JSONArray, then null elements will be added as necessary to pad
646: * it out.
647: * @param index The subscript.
648: * @param value An int value.
649: * @return this.
650: * @throws JSONException If the index is negative.
651: */
652: public JSONArray put(int index, int value) throws JSONException {
653: put(index, new Integer(value));
654: return this ;
655: }
656:
657: /**
658: * Put or replace a long value. If the index is greater than the length of
659: * the JSONArray, then null elements will be added as necessary to pad
660: * it out.
661: * @param index The subscript.
662: * @param value A long value.
663: * @return this.
664: * @throws JSONException If the index is negative.
665: */
666: public JSONArray put(int index, long value) throws JSONException {
667: put(index, new Long(value));
668: return this ;
669: }
670:
671: /**
672: * Put a value in the JSONArray, where the value will be a
673: * JSONObject which is produced from a Map.
674: * @param index The subscript.
675: * @param value The Map value.
676: * @return this.
677: * @throws JSONException If the index is negative or if the the value is
678: * an invalid number.
679: */
680: public JSONArray put(int index, Map value) throws JSONException {
681: put(index, new JSONObject(value));
682: return this ;
683: }
684:
685: /**
686: * Put or replace an object value in the JSONArray. If the index is greater
687: * than the length of the JSONArray, then null elements will be added as
688: * necessary to pad it out.
689: * @param index The subscript.
690: * @param value The value to put into the array. The value should be a
691: * Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the
692: * JSONObject.NULL object.
693: * @return this.
694: * @throws JSONException If the index is negative or if the the value is
695: * an invalid number.
696: */
697: public JSONArray put(int index, Object value) throws JSONException {
698: JSONObject.testValidity(value);
699: if (index < 0) {
700: throw new JSONException("JSONArray[" + index
701: + "] not found.");
702: }
703: if (index < length()) {
704: this .myArrayList.set(index, value);
705: } else {
706: while (index != length()) {
707: put(JSONObject.NULL);
708: }
709: put(value);
710: }
711: return this ;
712: }
713:
714: /**
715: * Produce a JSONObject by combining a JSONArray of names with the values
716: * of this JSONArray.
717: * @param names A JSONArray containing a list of key strings. These will be
718: * paired with the values.
719: * @return A JSONObject, or null if there are no names or if this JSONArray
720: * has no values.
721: * @throws JSONException If any of the names are null.
722: */
723: public JSONObject toJSONObject(JSONArray names)
724: throws JSONException {
725: if (names == null || names.length() == 0 || length() == 0) {
726: return null;
727: }
728: JSONObject jo = new JSONObject();
729: for (int i = 0; i < names.length(); i += 1) {
730: jo.put(names.getString(i), this .opt(i));
731: }
732: return jo;
733: }
734:
735: /**
736: * Make a JSON text of this JSONArray. For compactness, no
737: * unnecessary whitespace is added. If it is not possible to produce a
738: * syntactically correct JSON text then null will be returned instead. This
739: * could occur if the array contains an invalid number.
740: * <p>
741: * Warning: This method assumes that the data structure is acyclical.
742: *
743: * @return a printable, displayable, transmittable
744: * representation of the array.
745: */
746: public String toString() {
747: try {
748: return '[' + join(",") + ']';
749: } catch (Exception e) {
750: return null;
751: }
752: }
753:
754: /**
755: * Make a prettyprinted JSON text of this JSONArray.
756: * Warning: This method assumes that the data structure is acyclical.
757: * @param indentFactor The number of spaces to add to each level of
758: * indentation.
759: * @return a printable, displayable, transmittable
760: * representation of the object, beginning
761: * with <code>[</code> <small>(left bracket)</small> and ending
762: * with <code>]</code> <small>(right bracket)</small>.
763: * @throws JSONException
764: */
765: public String toString(int indentFactor) throws JSONException {
766: return toString(indentFactor, 0);
767: }
768:
769: /**
770: * Make a prettyprinted JSON text of this JSONArray.
771: * Warning: This method assumes that the data structure is acyclical.
772: * @param indentFactor The number of spaces to add to each level of
773: * indentation.
774: * @param indent The indention of the top level.
775: * @return a printable, displayable, transmittable
776: * representation of the array.
777: * @throws JSONException
778: */
779: String toString(int indentFactor, int indent) throws JSONException {
780: int len = length();
781: if (len == 0) {
782: return "[]";
783: }
784: int i;
785: StringBuffer sb = new StringBuffer("[");
786: if (len == 1) {
787: sb.append(JSONObject.valueToString(this .myArrayList.get(0),
788: indentFactor, indent));
789: } else {
790: int newindent = indent + indentFactor;
791: sb.append('\n');
792: for (i = 0; i < len; i += 1) {
793: if (i > 0) {
794: sb.append(",\n");
795: }
796: for (int j = 0; j < newindent; j += 1) {
797: sb.append(' ');
798: }
799: sb.append(JSONObject.valueToString(this .myArrayList
800: .get(i), indentFactor, newindent));
801: }
802: sb.append('\n');
803: for (i = 0; i < indent; i += 1) {
804: sb.append(' ');
805: }
806: }
807: sb.append(']');
808: return sb.toString();
809: }
810:
811: /**
812: * Write the contents of the JSONArray as JSON text to a writer.
813: * For compactness, no whitespace is added.
814: * <p>
815: * Warning: This method assumes that the data structure is acyclical.
816: *
817: * @return The writer.
818: * @throws JSONException
819: */
820: public Writer write(Writer writer) throws JSONException {
821: try {
822: boolean b = false;
823: int len = length();
824:
825: writer.write('[');
826:
827: for (int i = 0; i < len; i += 1) {
828: if (b) {
829: writer.write(',');
830: }
831: Object v = this .myArrayList.get(i);
832: if (v instanceof JSONObject) {
833: ((JSONObject) v).write(writer);
834: } else if (v instanceof JSONArray) {
835: ((JSONArray) v).write(writer);
836: } else {
837: writer.write(JSONObject.valueToString(v));
838: }
839: b = true;
840: }
841: writer.write(']');
842: return writer;
843: } catch (IOException e) {
844: throw new JSONException(e);
845: }
846: }
847: }
|