diff --git a/JSONArray.java b/JSONArray.java index 4ae610f..71c277a 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -25,6 +25,7 @@ SOFTWARE. */ import java.io.IOException; +import java.io.StringWriter; import java.io.Writer; import java.lang.reflect.Array; import java.util.ArrayList; @@ -60,23 +61,23 @@ import java.util.Map; * accept: *
,
(comma) may appear just
- * before the closing bracket.null
value will be inserted when there
- * is ,
(comma) elision.null
value will be inserted when there is ,
+ * (comma) elision.'
(single
- * quote).{ } [ ] / \ : , = ; #
and if they do not look like numbers
- * and if they are not the reserved words true
,
- * false
, or null
.{ } [ ] / \ : , = ; #
and if they do not look like numbers and
+ * if they are not the reserved words true
, false
, or
+ * null
.
* ;
(semicolon) as
- * well as by ,
(comma).,
(comma).
* * Warning: This method assumes that the data structure is acyclical. * @@ -891,25 +851,51 @@ public class JSONArray { * @throws JSONException */ public Writer write(Writer writer) throws JSONException { - try { - boolean b = false; - int len = this.length(); + return this.write(writer, 0, 0); + } + /** + * Write the contents of the JSONArray as JSON text to a writer. For + * compactness, no whitespace is added. + *
+ * Warning: This method assumes that the data structure is acyclical.
+ *
+ * @param indentFactor
+ * The number of spaces to add to each level of indentation.
+ * @param indent
+ * The indention of the top level.
+ * @return The writer.
+ * @throws JSONException
+ */
+ Writer write(Writer writer, int indentFactor, int indent)
+ throws JSONException {
+ try {
+ boolean commanate = false;
+ int length = this.length();
writer.write('[');
- for (int i = 0; i < len; i += 1) {
- if (b) {
- writer.write(',');
+ if (length == 1) {
+ JSONObject.writeValue(writer, this.myArrayList.get(0),
+ indentFactor, indent);
+ } else if (length != 0) {
+ final int newindent = indent + indentFactor;
+
+ for (int i = 0; i < length; i += 1) {
+ if (commanate) {
+ writer.write(',');
+ }
+ if (indentFactor > 0) {
+ writer.write('\n');
+ }
+ JSONObject.indent(writer, newindent);
+ JSONObject.writeValue(writer, this.myArrayList.get(i),
+ indentFactor, newindent);
+ commanate = true;
}
- Object v = this.myArrayList.get(i);
- if (v instanceof JSONObject) {
- ((JSONObject)v).write(writer);
- } else if (v instanceof JSONArray) {
- ((JSONArray)v).write(writer);
- } else {
- writer.write(JSONObject.valueToString(v));
+ if (indentFactor > 0) {
+ writer.write('\n');
}
- b = true;
+ JSONObject.indent(writer, indent);
}
writer.write(']');
return writer;
@@ -917,4 +903,4 @@ public class JSONArray {
throw new JSONException(e);
}
}
-}
\ No newline at end of file
+}
diff --git a/JSONObject.java b/JSONObject.java
index f8ee359..5b05255 100755
--- a/JSONObject.java
+++ b/JSONObject.java
@@ -25,10 +25,11 @@ SOFTWARE.
*/
import java.io.IOException;
+import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
@@ -38,54 +39,58 @@ import java.util.Map;
import java.util.ResourceBundle;
/**
- * A JSONObject is an unordered collection of name/value pairs. Its
- * external form is a string wrapped in curly braces with colons between the
- * names and values, and commas between the values and names. The internal form
- * is an object having get
and opt
methods for
- * accessing the values by name, and put
methods for adding or
- * replacing values by name. The values can be any of these types:
- * Boolean
, JSONArray
, JSONObject
,
- * Number
, String
, or the JSONObject.NULL
- * object. A JSONObject constructor can be used to convert an external form
- * JSON text into an internal form whose values can be retrieved with the
- * get
and opt
methods, or to convert values into a
- * JSON text using the put
and toString
methods.
- * A get
method returns a value if one can be found, and throws an
- * exception if one cannot be found. An opt
method returns a
- * default value instead of throwing an exception, and so is useful for
- * obtaining optional values.
+ * A JSONObject is an unordered collection of name/value pairs. Its external
+ * form is a string wrapped in curly braces with colons between the names and
+ * values, and commas between the values and names. The internal form is an
+ * object having get
and opt
methods for accessing the
+ * values by name, and put
methods for adding or replacing values
+ * by name. The values can be any of these types: Boolean
,
+ * JSONArray
, JSONObject
, Number
,
+ * String
, or the JSONObject.NULL
object. A JSONObject
+ * constructor can be used to convert an external form JSON text into an
+ * internal form whose values can be retrieved with the get
and
+ * opt
methods, or to convert values into a JSON text using the
+ * put
and toString
methods. A get
method
+ * returns a value if one can be found, and throws an exception if one cannot be
+ * found. An opt
method returns a default value instead of throwing
+ * an exception, and so is useful for obtaining optional values.
*
* The generic get()
and opt()
methods return an
* object, which you can cast or query for type. There are also typed
* get
and opt
methods that do type checking and type
- * coercion for you. The opt methods differ from the get methods in that they
- * do not throw. Instead, they return a specified value, such as null.
+ * coercion for you. The opt methods differ from the get methods in that they do
+ * not throw. Instead, they return a specified value, such as null.
*
* The put
methods add or replace values in an object. For example,
- *
myString = new JSONObject().put("JSON", "Hello, World!").toString();+ * + *
+ * myString = new JSONObject().put("JSON", "Hello, World!").toString(); + *+ * * produces the string
{"JSON": "Hello, World"}
.
*
* The texts produced by the toString
methods strictly conform to
- * the JSON syntax rules.
- * The constructors are more forgiving in the texts they will accept:
+ * the JSON syntax rules. The constructors are more forgiving in the texts they
+ * will accept:
*
,
(comma) may appear just
- * before the closing brace.'
(single
- * quote).{ } [ ] / \ : , = ; #
and if they do not look like numbers
- * and if they are not the reserved words true
,
- * false
, or null
.=
or =>
as well as
- * by :
.{ } [ ] / \ : , = ; #
and if they do not look like numbers and
+ * if they are not the reserved words true
, false
, or
+ * null
.
+ * =
or =>
as well as by
+ * :
.;
(semicolon) as
- * well as by ,
(comma).,
(comma).
*
- * Warning: This method assumes that the data structure is acyclical.
- * @param indentFactor The number of spaces to add to each level of
- * indentation.
- * @param indent The indentation of the top level.
- * @return a printable, displayable, transmittable
- * representation of the object, beginning
- * with {
(left brace) and ending
- * with }
(right brace).
- * @throws JSONException If the object contains an invalid number.
- */
- String toString(int indentFactor, int indent) throws JSONException {
- int i;
- int length = this.length();
- if (length == 0) {
- return "{}";
+ StringWriter w = new StringWriter();
+ synchronized (w.getBuffer()) {
+ return this.write(w, indentFactor, 0).toString();
}
- Iterator keys = this.keys();
- int newindent = indent + indentFactor;
- Object object;
- StringBuffer sb = new StringBuffer("{");
- if (length == 1) {
- object = keys.next();
- sb.append(quote(object.toString()));
- sb.append(": ");
- sb.append(valueToString(this.map.get(object), indentFactor,
- indent));
- } else {
- while (keys.hasNext()) {
- object = keys.next();
- if (sb.length() > 1) {
- sb.append(",\n");
- } else {
- sb.append('\n');
- }
- for (i = 0; i < newindent; i += 1) {
- sb.append(' ');
- }
- sb.append(quote(object.toString()));
- sb.append(": ");
- sb.append(valueToString(this.map.get(object), indentFactor,
- newindent));
- }
- if (sb.length() > 1) {
- sb.append('\n');
- for (i = 0; i < indent; i += 1) {
- sb.append(' ');
- }
- }
- }
- sb.append('}');
- return sb.toString();
}
-
/**
* Make a JSON text of an Object value. If the object has an
* value.toJSONString() method, then that method will be used to produce
@@ -1478,63 +1427,6 @@ public class JSONObject {
return quote(value.toString());
}
-
- /**
- * Make a prettyprinted JSON text of an object value.
- *
- * Warning: This method assumes that the data structure is acyclical.
- * @param value The value to be serialized.
- * @param indentFactor The number of spaces to add to each level of
- * indentation.
- * @param indent The indentation of the top level.
- * @return a printable, displayable, transmittable
- * representation of the object, beginning
- * with {
(left brace) and ending
- * with }
(right brace).
- * @throws JSONException If the object contains an invalid number.
- */
- static String valueToString(
- Object value,
- int indentFactor,
- int indent
- ) throws JSONException {
- if (value == null || value.equals(null)) {
- return "null";
- }
- try {
- if (value instanceof JSONString) {
- Object o = ((JSONString)value).toJSONString();
- if (o instanceof String) {
- return (String)o;
- }
- }
- } catch (Exception ignore) {
- }
- if (value instanceof Number) {
- return numberToString((Number) value);
- }
- if (value instanceof Boolean) {
- return value.toString();
- }
- if (value instanceof JSONObject) {
- return ((JSONObject)value).toString(indentFactor, indent);
- }
- if (value instanceof JSONArray) {
- return ((JSONArray)value).toString(indentFactor, indent);
- }
- if (value instanceof Map) {
- return new JSONObject((Map)value).toString(indentFactor, indent);
- }
- if (value instanceof Collection) {
- return new JSONArray((Collection)value).toString(indentFactor, indent);
- }
- if (value.getClass().isArray()) {
- return new JSONArray(value).toString(indentFactor, indent);
- }
- return quote(value.toString());
- }
-
-
/**
* Wrap an object, if necessary. If the object is null, return the NULL
* object. If it is an array or collection, wrap it in a JSONArray. If
@@ -1599,27 +1491,98 @@ public class JSONObject {
* @throws JSONException
*/
public Writer write(Writer writer) throws JSONException {
+ return this.write(writer, 0, 0);
+ }
+
+
+ static final Writer writeValue(Writer writer, Object value,
+ int indentFactor, int indent) throws JSONException, IOException {
+ if (value instanceof JSONObject) {
+ ((JSONObject) value).write(writer, indentFactor, indent);
+ } else if (value instanceof JSONArray) {
+ ((JSONArray) value).write(writer, indentFactor, indent);
+ } else if (value instanceof Map) {
+ new JSONObject((Map) value).write(writer, indentFactor, indent);
+ } else if (value instanceof Collection) {
+ new JSONArray((Collection) value).write(writer, indentFactor,
+ indent);
+ } else if (value.getClass().isArray()) {
+ new JSONArray(value).write(writer, indentFactor, indent);
+ } else if (value instanceof Number) {
+ writer.write(numberToString((Number) value));
+ } else if (value instanceof Boolean) {
+ writer.write(value.toString());
+ } else if (value instanceof JSONString) {
+ Object o;
+ try {
+ o = ((JSONString) value).toJSONString();
+ } catch (Exception e) {
+ throw new JSONException(e);
+ }
+ writer.write(o != null ? o.toString() : quote(value.toString()));
+ } else if (value == null || value.equals(null)) {
+ writer.write("null");
+ } else {
+ quote(value.toString(), writer);
+ }
+ return writer;
+ }
+
+ static final void indent(Writer writer, int indent) throws IOException {
+ for (int i = 0; i < indent; i += 1) {
+ writer.write(' ');
+ }
+ }
+
+ /**
+ * Write the contents of the JSONObject as JSON text to a writer. For
+ * compactness, no whitespace is added.
+ *
+ * Warning: This method assumes that the data structure is acyclical. + * + * @return The writer. + * @throws JSONException + */ + Writer write(Writer writer, int indentFactor, int indent) + throws JSONException { try { - boolean commanate = false; + boolean commanate = false; + final int length = this.length(); Iterator keys = this.keys(); writer.write('{'); - while (keys.hasNext()) { - if (commanate) { - writer.write(','); - } + if (length == 1) { Object key = keys.next(); writer.write(quote(key.toString())); writer.write(':'); - Object value = this.map.get(key); - if (value instanceof JSONObject) { - ((JSONObject)value).write(writer); - } else if (value instanceof JSONArray) { - ((JSONArray)value).write(writer); - } else { - writer.write(valueToString(value)); + if (indentFactor > 0) { + writer.write(' '); } - commanate = true; + writeValue(writer, this.map.get(key), indentFactor, indent); + } else if (length != 0) { + final int newindent = indent + indentFactor; + while (keys.hasNext()) { + Object key = keys.next(); + if (commanate) { + writer.write(','); + } + if (indentFactor > 0) { + writer.write('\n'); + } + indent(writer, newindent); + writer.write(quote(key.toString())); + writer.write(':'); + if (indentFactor > 0) { + writer.write(' '); + } + writeValue(writer, this.map.get(key), indentFactor, + newindent); + commanate = true; + } + if (indentFactor > 0) { + writer.write('\n'); + } + indent(writer, indent); } writer.write('}'); return writer; @@ -1627,4 +1590,4 @@ public class JSONObject { throw new JSONException(exception); } } -} \ No newline at end of file +}