From e2b3573947273a1931af8e29cc684977d0640976 Mon Sep 17 00:00:00 2001 From: Mario Carneiro Date: Fri, 8 Jan 2016 18:20:40 -0500 Subject: [PATCH 1/6] let JSONArray and JSONObject implement Map and List --- JSONArray.java | 59 ++++++++++----------------- JSONObject.java | 106 ++++++++++++++++++++---------------------------- JSONWriter.java | 2 +- 3 files changed, 68 insertions(+), 99 deletions(-) diff --git a/JSONArray.java b/JSONArray.java index a3df9758a..5d9fd6009 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -28,10 +28,10 @@ of this software and associated documentation files (the "Software"), to deal import java.io.StringWriter; import java.io.Writer; import java.lang.reflect.Array; -import java.math.*; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; import java.util.Map; /** @@ -78,18 +78,13 @@ of this software and associated documentation files (the "Software"), to deal * @author JSON.org * @version 2015-10-29 */ -public class JSONArray implements Iterable { - - /** - * The arrayList where the JSONArray's properties are kept. - */ - private final ArrayList myArrayList; +public class JSONArray extends ArrayList { /** * Construct an empty JSONArray. */ public JSONArray() { - this.myArrayList = new ArrayList(); + super(); } /** @@ -110,10 +105,10 @@ public JSONArray(JSONTokener x) throws JSONException { for (;;) { if (x.nextClean() == ',') { x.back(); - this.myArrayList.add(JSONObject.NULL); + super.add(JSONObject.NULL); } else { x.back(); - this.myArrayList.add(x.nextValue()); + super.add(x.nextValue()); } switch (x.nextClean()) { case ',': @@ -152,11 +147,11 @@ public JSONArray(String source) throws JSONException { * A Collection. */ public JSONArray(Collection collection) { - this.myArrayList = new ArrayList(); + this(); if (collection != null) { - for (Object o: collection){ - this.myArrayList.add(JSONObject.wrap(o)); - } + for (Object o: collection){ + super.add(JSONObject.wrap(o)); + } } } @@ -179,11 +174,6 @@ public JSONArray(Object array) throws JSONException { } } - @Override - public Iterator iterator() { - return myArrayList.iterator(); - } - /** * Get the object value associated with an index. * @@ -433,7 +423,7 @@ public String join(String separator) throws JSONException { if (i > 0) { sb.append(separator); } - sb.append(JSONObject.valueToString(this.myArrayList.get(i))); + sb.append(JSONObject.valueToString(super.get(i))); } return sb.toString(); } @@ -444,7 +434,7 @@ public String join(String separator) throws JSONException { * @return The length (or size). */ public int length() { - return this.myArrayList.size(); + return size(); } /** @@ -455,8 +445,7 @@ public int length() { * @return An object value, or null if there is no object at that index. */ public Object opt(int index) { - return (index < 0 || index >= this.length()) ? null : this.myArrayList - .get(index); + return (index < 0 || index >= this.length()) ? null : super.get(index); } /** @@ -746,8 +735,7 @@ public JSONArray put(boolean value) { * @return this. */ public JSONArray put(Collection value) { - this.put(new JSONArray(value)); - return this; + return put((Object) (value instanceof JSONArray ? value : new JSONArray(value))); } /** @@ -799,8 +787,7 @@ public JSONArray put(long value) { * @return this. */ public JSONArray put(Map value) { - this.put(new JSONObject(value)); - return this; + return put((Object) (value instanceof JSONObject ? value : new JSONObject(value))); } /** @@ -813,7 +800,7 @@ public JSONArray put(Map value) { * @return this. */ public JSONArray put(Object value) { - this.myArrayList.add(value); + super.add(value); return this; } @@ -848,8 +835,7 @@ public JSONArray put(int index, boolean value) throws JSONException { * If the index is negative or if the value is not finite. */ public JSONArray put(int index, Collection value) throws JSONException { - this.put(index, new JSONArray(value)); - return this; + return put(index, (Object) (value instanceof JSONArray ? value : new JSONArray(value))); } /** @@ -920,8 +906,7 @@ public JSONArray put(int index, long value) throws JSONException { * number. */ public JSONArray put(int index, Map value) throws JSONException { - this.put(index, new JSONObject(value)); - return this; + return put(index, (Object) (value instanceof JSONObject ? value : new JSONObject(value))); } /** @@ -946,7 +931,7 @@ public JSONArray put(int index, Object value) throws JSONException { throw new JSONException("JSONArray[" + index + "] not found."); } if (index < this.length()) { - this.myArrayList.set(index, value); + super.set(index, value); } else { while (index != this.length()) { this.put(JSONObject.NULL); @@ -966,7 +951,7 @@ public JSONArray put(int index, Object value) throws JSONException { */ public Object remove(int index) { return index >= 0 && index < this.length() - ? this.myArrayList.remove(index) + ? super.remove(index) : null; } @@ -1100,7 +1085,7 @@ public Writer write(Writer writer, int indentFactor, int indent) writer.write('['); if (length == 1) { - JSONObject.writeValue(writer, this.myArrayList.get(0), + JSONObject.writeValue(writer, super.get(0), indentFactor, indent); } else if (length != 0) { final int newindent = indent + indentFactor; @@ -1113,7 +1098,7 @@ public Writer write(Writer writer, int indentFactor, int indent) writer.write('\n'); } JSONObject.indent(writer, newindent); - JSONObject.writeValue(writer, this.myArrayList.get(i), + JSONObject.writeValue(writer, super.get(i), indentFactor, newindent); commanate = true; } diff --git a/JSONObject.java b/JSONObject.java index 2f613f855..e654278a5 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -37,7 +37,6 @@ of this software and associated documentation files (the "Software"), to deal import java.util.Iterator; import java.util.Locale; import java.util.Map; -import java.util.Map.Entry; import java.util.ResourceBundle; import java.util.Set; @@ -94,7 +93,7 @@ of this software and associated documentation files (the "Software"), to deal * @author JSON.org * @version 2015-12-09 */ -public class JSONObject { +public class JSONObject extends HashMap { /** * JSONObject.NULL is equivalent to the value that JavaScript calls null, * whilst Java's null is equivalent to the value that JavaScript calls @@ -131,16 +130,12 @@ public boolean equals(Object object) { * * @return The string "null". */ + @Override public String toString() { return "null"; } } - /** - * The map where the JSONObject's properties are kept. - */ - private final Map map; - /** * It is sometimes more convenient and less ambiguous to have a * NULL object than to use Java's null value. @@ -153,7 +148,7 @@ public String toString() { * Construct an empty JSONObject. */ public JSONObject() { - this.map = new HashMap(); + super(); } /** @@ -170,7 +165,7 @@ public JSONObject(JSONObject jo, String[] names) { this(); for (int i = 0; i < names.length; i += 1) { try { - this.putOnce(names[i], jo.opt(names[i])); + putOnce(names[i], jo.opt(names[i])); } catch (Exception ignore) { } } @@ -211,7 +206,7 @@ public JSONObject(JSONTokener x) throws JSONException { if (c != ':') { throw x.syntaxError("Expected a ':' after a key"); } - this.putOnce(key, x.nextValue()); + putOnce(key, x.nextValue()); // Pairs are separated by ','. @@ -239,12 +234,12 @@ public JSONObject(JSONTokener x) throws JSONException { * the JSONObject. */ public JSONObject(Map map) { - this.map = new HashMap(); + this(); if (map != null) { - for (final Entry e : map.entrySet()) { + for (final Entry e : map.entrySet()) { final Object value = e.getValue(); if (value != null) { - this.map.put(String.valueOf(e.getKey()), wrap(value)); + super.put(String.valueOf(e.getKey()), wrap(value)); } } } @@ -273,7 +268,7 @@ public JSONObject(Map map) { */ public JSONObject(Object bean) { this(); - this.populateMap(bean); + populateMap(bean); } /** @@ -296,7 +291,7 @@ public JSONObject(Object object, String names[]) { for (int i = 0; i < names.length; i += 1) { String name = names[i]; try { - this.putOpt(name, c.getField(name).get(object)); + putOpt(name, c.getField(name).get(object)); } catch (Exception ignore) { } } @@ -382,11 +377,9 @@ public JSONObject(String baseName, Locale locale) throws JSONException { */ public JSONObject accumulate(String key, Object value) throws JSONException { testValidity(value); - Object object = this.opt(key); + Object object = opt(key); if (object == null) { - this.put(key, - value instanceof JSONArray ? new JSONArray().put(value) - : value); + put(key, value instanceof JSONArray ? new JSONArray().put(value) : value); } else if (object instanceof JSONArray) { ((JSONArray) object).put(value); } else { @@ -412,7 +405,7 @@ public JSONObject accumulate(String key, Object value) throws JSONException { */ public JSONObject append(String key, Object value) throws JSONException { testValidity(value); - Object object = this.opt(key); + Object object = opt(key); if (object == null) { this.put(key, new JSONArray().put(value)); } else if (object instanceof JSONArray) { @@ -465,7 +458,7 @@ public Object get(String key) throws JSONException { if (key == null) { throw new JSONException("Null key."); } - Object object = this.opt(key); + Object object = opt(key); if (object == null) { throw new JSONException("JSONObject[" + quote(key) + "] not found."); } @@ -728,7 +721,7 @@ public String getString(String key) throws JSONException { * @return true if the key exists in the JSONObject. */ public boolean has(String key) { - return this.map.containsKey(key); + return containsKey(key); } /** @@ -744,7 +737,7 @@ public boolean has(String key) { * Integer, Long, Double, or Float. */ public JSONObject increment(String key) throws JSONException { - Object value = this.opt(key); + Object value = opt(key); if (value == null) { this.put(key, 1); } else if (value instanceof BigInteger) { @@ -775,7 +768,7 @@ public JSONObject increment(String key) throws JSONException { * is the JSONObject.NULL object. */ public boolean isNull(String key) { - return JSONObject.NULL.equals(this.opt(key)); + return JSONObject.NULL.equals(opt(key)); } /** @@ -784,16 +777,7 @@ public boolean isNull(String key) { * @return An iterator of the keys. */ public Iterator keys() { - return this.keySet().iterator(); - } - - /** - * Get a set of keys of the JSONObject. - * - * @return A keySet. - */ - public Set keySet() { - return this.map.keySet(); + return keySet().iterator(); } /** @@ -802,7 +786,7 @@ public Set keySet() { * @return The number of keys in the JSONObject. */ public int length() { - return this.map.size(); + return super.size(); } /** @@ -814,7 +798,7 @@ public int length() { */ public JSONArray names() { JSONArray ja = new JSONArray(); - Iterator keys = this.keys(); + Iterator keys = keys(); while (keys.hasNext()) { ja.put(keys.next()); } @@ -859,7 +843,7 @@ public static String numberToString(Number number) throws JSONException { * @return An object which is the value, or null if there is no value. */ public Object opt(String key) { - return key == null ? null : this.map.get(key); + return key == null ? null : super.get(key); } /** @@ -889,7 +873,7 @@ public > E optEnum(Class clazz, String key) { */ public > E optEnum(Class clazz, String key, E defaultValue) { try { - Object val = this.opt(key); + Object val = opt(key); if (NULL.equals(val)) { return defaultValue; } @@ -930,7 +914,7 @@ public boolean optBoolean(String key) { */ public boolean optBoolean(String key, boolean defaultValue) { try { - return this.getBoolean(key); + return getBoolean(key); } catch (Exception e) { return defaultValue; } @@ -962,7 +946,7 @@ public double optDouble(String key) { */ public BigInteger optBigInteger(String key, BigInteger defaultValue) { try { - return this.getBigInteger(key); + return getBigInteger(key); } catch (Exception e) { return defaultValue; } @@ -981,7 +965,7 @@ public BigInteger optBigInteger(String key, BigInteger defaultValue) { */ public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) { try { - return this.getBigDecimal(key); + return getBigDecimal(key); } catch (Exception e) { return defaultValue; } @@ -1000,7 +984,7 @@ public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) { */ public double optDouble(String key, double defaultValue) { try { - return this.getDouble(key); + return getDouble(key); } catch (Exception e) { return defaultValue; } @@ -1032,7 +1016,7 @@ public int optInt(String key) { */ public int optInt(String key, int defaultValue) { try { - return this.getInt(key); + return getInt(key); } catch (Exception e) { return defaultValue; } @@ -1047,7 +1031,7 @@ public int optInt(String key, int defaultValue) { * @return A JSONArray which is the value. */ public JSONArray optJSONArray(String key) { - Object o = this.opt(key); + Object o = opt(key); return o instanceof JSONArray ? (JSONArray) o : null; } @@ -1060,7 +1044,7 @@ public JSONArray optJSONArray(String key) { * @return A JSONObject which is the value. */ public JSONObject optJSONObject(String key) { - Object object = this.opt(key); + Object object = opt(key); return object instanceof JSONObject ? (JSONObject) object : null; } @@ -1090,7 +1074,7 @@ public long optLong(String key) { */ public long optLong(String key, long defaultValue) { try { - return this.getLong(key); + return getLong(key); } catch (Exception e) { return defaultValue; } @@ -1120,7 +1104,7 @@ public String optString(String key) { * @return A string which is the value. */ public String optString(String key, String defaultValue) { - Object object = this.opt(key); + Object object = opt(key); return NULL.equals(object) ? defaultValue : object.toString(); } @@ -1161,7 +1145,7 @@ private void populateMap(Object bean) { Object result = method.invoke(bean, (Object[]) null); if (result != null) { - this.map.put(key, wrap(result)); + super.put(key, wrap(result)); } } } @@ -1198,8 +1182,7 @@ public JSONObject put(String key, boolean value) throws JSONException { * @throws JSONException */ public JSONObject put(String key, Collection value) throws JSONException { - this.put(key, new JSONArray(value)); - return this; + return put(key, (Object) (value instanceof JSONArray ? value : new JSONArray(value))); } /** @@ -1262,8 +1245,7 @@ public JSONObject put(String key, long value) throws JSONException { * @throws JSONException */ public JSONObject put(String key, Map value) throws JSONException { - this.put(key, new JSONObject(value)); - return this; + return put(key, (Object) (value instanceof JSONObject ? value : new JSONObject(value))); } /** @@ -1280,13 +1262,14 @@ public JSONObject put(String key, Map value) throws JSONException { * @throws JSONException * If the value is non-finite number or if the key is null. */ + @Override public JSONObject put(String key, Object value) throws JSONException { if (key == null) { throw new NullPointerException("Null key."); } if (value != null) { testValidity(value); - this.map.put(key, value); + super.put(key, value); } else { this.remove(key); } @@ -1306,7 +1289,7 @@ public JSONObject put(String key, Object value) throws JSONException { */ public JSONObject putOnce(String key, Object value) throws JSONException { if (key != null && value != null) { - if (this.opt(key) != null) { + if (opt(key) != null) { throw new JSONException("Duplicate key \"" + key + "\""); } this.put(key, value); @@ -1425,7 +1408,7 @@ public static Writer quote(String string, Writer w) throws IOException { * no value. */ public Object remove(String key) { - return this.map.remove(key); + return super.remove(key); } /** @@ -1441,7 +1424,7 @@ public boolean similar(Object other) { if (!(other instanceof JSONObject)) { return false; } - Set set = this.keySet(); + Set set = keySet(); if (!set.equals(((JSONObject)other).keySet())) { return false; } @@ -1562,7 +1545,7 @@ public JSONArray toJSONArray(JSONArray names) throws JSONException { } JSONArray ja = new JSONArray(); for (int i = 0; i < names.length(); i += 1) { - ja.put(this.opt(names.getString(i))); + ja.put(opt(names.getString(i))); } return ja; } @@ -1579,6 +1562,7 @@ public JSONArray toJSONArray(JSONArray names) throws JSONException { * brace) and ending with } (right * brace). */ + @Override public String toString() { try { return this.toString(0); @@ -1794,8 +1778,8 @@ public Writer write(Writer writer, int indentFactor, int indent) throws JSONException { try { boolean commanate = false; - final int length = this.length(); - Iterator keys = this.keys(); + final int length = length(); + Iterator keys = keys(); writer.write('{'); if (length == 1) { @@ -1805,7 +1789,7 @@ public Writer write(Writer writer, int indentFactor, int indent) if (indentFactor > 0) { writer.write(' '); } - writeValue(writer, this.map.get(key), indentFactor, indent); + writeValue(writer, super.get(key), indentFactor, indent); } else if (length != 0) { final int newindent = indent + indentFactor; while (keys.hasNext()) { @@ -1822,7 +1806,7 @@ public Writer write(Writer writer, int indentFactor, int indent) if (indentFactor > 0) { writer.write(' '); } - writeValue(writer, this.map.get(key), indentFactor, newindent); + writeValue(writer, super.get(key), indentFactor, newindent); commanate = true; } if (indentFactor > 0) { diff --git a/JSONWriter.java b/JSONWriter.java index 09d113030..0ba0b834a 100644 --- a/JSONWriter.java +++ b/JSONWriter.java @@ -50,7 +50,7 @@ of this software and associated documentation files (the "Software"), to deal *

* The first method called must be array or object. * There are no methods for adding commas or colons. JSONWriter adds them for - * you. Objects and arrays can be nested up to 20 levels deep. + * you. Objects and arrays can be nested up to 200 levels deep. *

* This can sometimes be easier than using a JSONObject to build a string. * @author JSON.org From ccdd8c0bea20ac50a3f2f6f5e3e4593ae8038134 Mon Sep 17 00:00:00 2001 From: Mario Carneiro Date: Fri, 8 Jan 2016 16:24:52 -0500 Subject: [PATCH 2/6] add JSONWriter.end() --- JSONWriter.java | 117 ++++++++++++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 48 deletions(-) diff --git a/JSONWriter.java b/JSONWriter.java index 0ba0b834a..a9ee2cdc8 100644 --- a/JSONWriter.java +++ b/JSONWriter.java @@ -94,11 +94,11 @@ public class JSONWriter { * Make a fresh JSONWriter. It can be used to build one JSON text. */ public JSONWriter(Writer w) { - this.comma = false; - this.mode = 'i'; - this.stack = new JSONObject[maxdepth]; - this.top = 0; - this.writer = w; + comma = false; + mode = 'i'; + stack = new JSONObject[maxdepth]; + top = 0; + writer = w; } /** @@ -111,19 +111,19 @@ private JSONWriter append(String string) throws JSONException { if (string == null) { throw new JSONException("Null pointer"); } - if (this.mode == 'o' || this.mode == 'a') { + if (mode == 'o' || mode == 'a') { try { - if (this.comma && this.mode == 'a') { - this.writer.write(','); + if (comma && mode == 'a') { + writer.write(','); } - this.writer.write(string); + writer.write(string); } catch (IOException e) { throw new JSONException(e); } - if (this.mode == 'o') { - this.mode = 'k'; + if (mode == 'o') { + mode = 'k'; } - this.comma = true; + comma = true; return this; } throw new JSONException("Value out of sequence."); @@ -139,10 +139,10 @@ private JSONWriter append(String string) throws JSONException { * outermost array or object). */ public JSONWriter array() throws JSONException { - if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') { - this.push(null); - this.append("["); - this.comma = false; + if (mode == 'i' || mode == 'o' || mode == 'a') { + push(null); + append("["); + comma = false; return this; } throw new JSONException("Misplaced array."); @@ -161,13 +161,13 @@ private JSONWriter end(char mode, char c) throws JSONException { ? "Misplaced endArray." : "Misplaced endObject."); } - this.pop(mode); + pop(mode); try { - this.writer.write(c); + writer.write(c); } catch (IOException e) { throw new JSONException(e); } - this.comma = true; + comma = true; return this; } @@ -178,7 +178,7 @@ private JSONWriter end(char mode, char c) throws JSONException { * @throws JSONException If incorrectly nested. */ public JSONWriter endArray() throws JSONException { - return this.end('a', ']'); + return end('a', ']'); } /** @@ -188,9 +188,30 @@ public JSONWriter endArray() throws JSONException { * @throws JSONException If incorrectly nested. */ public JSONWriter endObject() throws JSONException { - return this.end('k', '}'); + return end('k', '}'); } + /** + * End an object or array. This method most be called to balance calls to + * object or array. + * @return this + * @throws JSONException If incorrectly nested. + */ + public JSONWriter end() throws JSONException { + char bracket; + switch (mode) { + case 'a': + bracket = ']'; + break; + case 'o': + bracket = '}'; + break; + default: + throw new JSONException("Misplaced end."); + } + return end(mode, bracket); + } + /** * Append a key. The key will be associated with the next value. In an * object, every value must be preceded by a key. @@ -203,16 +224,16 @@ public JSONWriter key(String string) throws JSONException { if (string == null) { throw new JSONException("Null key."); } - if (this.mode == 'k') { + if (mode == 'k') { try { - this.stack[this.top - 1].putOnce(string, Boolean.TRUE); - if (this.comma) { - this.writer.write(','); + stack[top - 1].putOnce(string, Boolean.TRUE); + if (comma) { + writer.write(','); } - this.writer.write(JSONObject.quote(string)); - this.writer.write(':'); - this.comma = false; - this.mode = 'o'; + writer.write(JSONObject.quote(string)); + writer.write(':'); + comma = false; + mode = 'o'; return this; } catch (IOException e) { throw new JSONException(e); @@ -232,13 +253,13 @@ public JSONWriter key(String string) throws JSONException { * outermost array or object). */ public JSONWriter object() throws JSONException { - if (this.mode == 'i') { - this.mode = 'o'; + if (mode == 'i') { + mode = 'o'; } - if (this.mode == 'o' || this.mode == 'a') { - this.append("{"); - this.push(new JSONObject()); - this.comma = false; + if (mode == 'o' || mode == 'a') { + append("{"); + push(new JSONObject()); + comma = false; return this; } throw new JSONException("Misplaced object."); @@ -252,17 +273,17 @@ public JSONWriter object() throws JSONException { * @throws JSONException If nesting is wrong. */ private void pop(char c) throws JSONException { - if (this.top <= 0) { + if (top <= 0) { throw new JSONException("Nesting error."); } - char m = this.stack[this.top - 1] == null ? 'a' : 'k'; + char m = stack[top - 1] == null ? 'a' : 'k'; if (m != c) { throw new JSONException("Nesting error."); } - this.top -= 1; - this.mode = this.top == 0 + top -= 1; + mode = top == 0 ? 'd' - : this.stack[this.top - 1] == null + : stack[top - 1] == null ? 'a' : 'k'; } @@ -273,12 +294,12 @@ private void pop(char c) throws JSONException { * @throws JSONException If nesting is too deep. */ private void push(JSONObject jo) throws JSONException { - if (this.top >= maxdepth) { + if (top >= maxdepth) { throw new JSONException("Nesting too deep."); } - this.stack[this.top] = jo; - this.mode = jo == null ? 'a' : 'k'; - this.top += 1; + stack[top] = jo; + mode = jo == null ? 'a' : 'k'; + top += 1; } @@ -290,7 +311,7 @@ private void push(JSONObject jo) throws JSONException { * @throws JSONException */ public JSONWriter value(boolean b) throws JSONException { - return this.append(b ? "true" : "false"); + return append(b ? "true" : "false"); } /** @@ -300,7 +321,7 @@ public JSONWriter value(boolean b) throws JSONException { * @throws JSONException If the number is not finite. */ public JSONWriter value(double d) throws JSONException { - return this.value(new Double(d)); + return value(new Double(d)); } /** @@ -310,7 +331,7 @@ public JSONWriter value(double d) throws JSONException { * @throws JSONException */ public JSONWriter value(long l) throws JSONException { - return this.append(Long.toString(l)); + return append(Long.toString(l)); } @@ -322,6 +343,6 @@ public JSONWriter value(long l) throws JSONException { * @throws JSONException If the value is out of sequence. */ public JSONWriter value(Object object) throws JSONException { - return this.append(JSONObject.valueToString(object)); + return append(JSONObject.valueToString(object)); } } From 59e1a29c0231a338e7d1eac983931dda635a48e2 Mon Sep 17 00:00:00 2001 From: Mario Carneiro Date: Fri, 8 Jan 2016 19:14:09 -0500 Subject: [PATCH 3/6] use char[] instead of JSONObject[] for the stack --- JSONWriter.java | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/JSONWriter.java b/JSONWriter.java index a9ee2cdc8..553204d18 100644 --- a/JSONWriter.java +++ b/JSONWriter.java @@ -78,7 +78,7 @@ public class JSONWriter { /** * The object/array stack. */ - private final JSONObject stack[]; + private final char stack[]; /** * The stack top index. A value of 0 indicates that the stack is empty. @@ -96,7 +96,7 @@ public class JSONWriter { public JSONWriter(Writer w) { comma = false; mode = 'i'; - stack = new JSONObject[maxdepth]; + stack = new char[maxdepth]; top = 0; writer = w; } @@ -140,7 +140,7 @@ private JSONWriter append(String string) throws JSONException { */ public JSONWriter array() throws JSONException { if (mode == 'i' || mode == 'o' || mode == 'a') { - push(null); + push('a'); append("["); comma = false; return this; @@ -226,7 +226,6 @@ public JSONWriter key(String string) throws JSONException { } if (mode == 'k') { try { - stack[top - 1].putOnce(string, Boolean.TRUE); if (comma) { writer.write(','); } @@ -258,7 +257,7 @@ public JSONWriter object() throws JSONException { } if (mode == 'o' || mode == 'a') { append("{"); - push(new JSONObject()); + push('k'); comma = false; return this; } @@ -276,16 +275,12 @@ private void pop(char c) throws JSONException { if (top <= 0) { throw new JSONException("Nesting error."); } - char m = stack[top - 1] == null ? 'a' : 'k'; + char m = stack[top - 1]; if (m != c) { throw new JSONException("Nesting error."); } top -= 1; - mode = top == 0 - ? 'd' - : stack[top - 1] == null - ? 'a' - : 'k'; + mode = top == 0 ? 'd' : stack[top - 1]; } /** @@ -293,12 +288,12 @@ private void pop(char c) throws JSONException { * @param jo The scope to open. * @throws JSONException If nesting is too deep. */ - private void push(JSONObject jo) throws JSONException { + private void push(char jo) throws JSONException { if (top >= maxdepth) { throw new JSONException("Nesting too deep."); } stack[top] = jo; - mode = jo == null ? 'a' : 'k'; + mode = jo; top += 1; } From 8a1b5a139ee2a1dd45726161da589b76df6335fe Mon Sep 17 00:00:00 2001 From: Mario Carneiro Date: Fri, 8 Jan 2016 20:28:45 -0500 Subject: [PATCH 4/6] restructure JSONWriter as a state machine --- JSONArray.java | 12 ++++ JSONWriter.java | 152 ++++++++++++++++++++++-------------------------- 2 files changed, 82 insertions(+), 82 deletions(-) diff --git a/JSONArray.java b/JSONArray.java index 5d9fd6009..15487e0e2 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -155,6 +155,18 @@ public JSONArray(Collection collection) { } } + /** + * Construct a JSONArray from an array + * @param The type of the array elements + */ + @SafeVarargs + public JSONArray(T... array) { + this(); + for (T x : array) { + this.put(JSONObject.wrap(x)); + } + } + /** * Construct a JSONArray from an array * diff --git a/JSONWriter.java b/JSONWriter.java index 553204d18..a67291907 100644 --- a/JSONWriter.java +++ b/JSONWriter.java @@ -2,6 +2,7 @@ import java.io.IOException; import java.io.Writer; +import java.util.BitSet; /* Copyright (c) 2006 JSON.org @@ -50,35 +51,33 @@ of this software and associated documentation files (the "Software"), to deal *

* The first method called must be array or object. * There are no methods for adding commas or colons. JSONWriter adds them for - * you. Objects and arrays can be nested up to 200 levels deep. + * you. *

* This can sometimes be easier than using a JSONObject to build a string. * @author JSON.org * @version 2015-12-09 */ public class JSONWriter { - private static final int maxdepth = 200; - - /** - * The comma flag determines if a comma should be output before the next - * value. - */ - private boolean comma; - /** * The current mode. Values: * 'a' (array), - * 'd' (done), - * 'i' (initial), - * 'k' (key), - * 'o' (object). + * 'A' (array after first element), + * 'i' (initial/done), + * 'k' (object: key), + * 'o' (object: value), + * 'K' (object: key after first element). + * + * The stack top is completely determined by the mode: it is empty in modes + * 'i', 'd', true (object) in modes 'k', 'o', 'K', and false (array) in + * modes 'a', 'A'. */ protected char mode; /** - * The object/array stack. + * The object/array stack. Stored as a BitSet, where objects are true and + * arrays are false. */ - private final char stack[]; + private final BitSet stack; /** * The stack top index. A value of 0 indicates that the stack is empty. @@ -94,9 +93,8 @@ public class JSONWriter { * Make a fresh JSONWriter. It can be used to build one JSON text. */ public JSONWriter(Writer w) { - comma = false; mode = 'i'; - stack = new char[maxdepth]; + stack = new BitSet(); top = 0; writer = w; } @@ -111,22 +109,35 @@ private JSONWriter append(String string) throws JSONException { if (string == null) { throw new JSONException("Null pointer"); } - if (mode == 'o' || mode == 'a') { - try { - if (comma && mode == 'a') { - writer.write(','); - } - writer.write(string); - } catch (IOException e) { - throw new JSONException(e); - } - if (mode == 'o') { - mode = 'k'; + if (mode == 'd') { + throw new JSONException("Value out of sequence."); + } + try { + if (mode == 'A' || mode == 'K') { + writer.write(','); + } else if (mode == 'o') { + writer.write(':'); } - comma = true; - return this; + writer.write(string); + } catch (IOException e) { + throw new JSONException(e); + } + switch (mode) { + case 'a': + mode = 'A'; + break; + case 'k': + case 'K': + mode = 'o'; + break; + case 'o': + mode = 'K'; + break; + case 'i': + mode = 'd'; + break; } - throw new JSONException("Value out of sequence."); + return this; } /** @@ -139,10 +150,9 @@ private JSONWriter append(String string) throws JSONException { * outermost array or object). */ public JSONWriter array() throws JSONException { - if (mode == 'i' || mode == 'o' || mode == 'a') { - push('a'); + if (mode == 'i' || mode == 'o' || mode == 'a' || mode == 'A') { append("["); - comma = false; + push(false); return this; } throw new JSONException("Misplaced array."); @@ -155,19 +165,13 @@ public JSONWriter array() throws JSONException { * @return this * @throws JSONException If unbalanced. */ - private JSONWriter end(char mode, char c) throws JSONException { - if (this.mode != mode) { - throw new JSONException(mode == 'a' - ? "Misplaced endArray." - : "Misplaced endObject."); - } - pop(mode); + private JSONWriter end(char c) throws JSONException { + pop(); try { writer.write(c); } catch (IOException e) { throw new JSONException(e); } - comma = true; return this; } @@ -178,7 +182,10 @@ private JSONWriter end(char mode, char c) throws JSONException { * @throws JSONException If incorrectly nested. */ public JSONWriter endArray() throws JSONException { - return end('a', ']'); + if (mode != 'a' && mode != 'A') { + throw new JSONException("Misplaced endArray."); + } + return end(']'); } /** @@ -188,7 +195,10 @@ public JSONWriter endArray() throws JSONException { * @throws JSONException If incorrectly nested. */ public JSONWriter endObject() throws JSONException { - return end('k', '}'); + if (mode != 'k' && mode != 'K') { + throw new JSONException("Misplaced endObject."); + } + return end('}'); } /** @@ -200,16 +210,18 @@ public JSONWriter endObject() throws JSONException { public JSONWriter end() throws JSONException { char bracket; switch (mode) { - case 'a': + case 'a': + case 'A': bracket = ']'; break; - case 'o': + case 'k': + case 'K': bracket = '}'; break; default: throw new JSONException("Misplaced end."); } - return end(mode, bracket); + return end(bracket); } /** @@ -224,19 +236,8 @@ public JSONWriter key(String string) throws JSONException { if (string == null) { throw new JSONException("Null key."); } - if (mode == 'k') { - try { - if (comma) { - writer.write(','); - } - writer.write(JSONObject.quote(string)); - writer.write(':'); - comma = false; - mode = 'o'; - return this; - } catch (IOException e) { - throw new JSONException(e); - } + if (mode == 'k' || mode == 'K') { + return append(JSONObject.quote(string)); } throw new JSONException("Misplaced key."); } @@ -252,13 +253,9 @@ public JSONWriter key(String string) throws JSONException { * outermost array or object). */ public JSONWriter object() throws JSONException { - if (mode == 'i') { - mode = 'o'; - } - if (mode == 'o' || mode == 'a') { + if (mode == 'i' || mode == 'o' || mode == 'a' || mode == 'A') { append("{"); - push('k'); - comma = false; + push(true); return this; } throw new JSONException("Misplaced object."); @@ -268,33 +265,24 @@ public JSONWriter object() throws JSONException { /** * Pop an array or object scope. - * @param c The scope to close. * @throws JSONException If nesting is wrong. */ - private void pop(char c) throws JSONException { + private void pop() throws JSONException { if (top <= 0) { throw new JSONException("Nesting error."); } - char m = stack[top - 1]; - if (m != c) { - throw new JSONException("Nesting error."); - } - top -= 1; - mode = top == 0 ? 'd' : stack[top - 1]; + top--; + mode = top == 0 ? 'd' : stack.get(top - 1) ? 'K' : 'A'; } /** * Push an array or object scope. - * @param jo The scope to open. + * @param b The scope to open. * @throws JSONException If nesting is too deep. */ - private void push(char jo) throws JSONException { - if (top >= maxdepth) { - throw new JSONException("Nesting too deep."); - } - stack[top] = jo; - mode = jo; - top += 1; + private void push(boolean b) throws JSONException { + stack.set(top++, b); + mode = b ? 'k' : 'a'; } From 2257a3a4599e666d18234b815433803162dd9a85 Mon Sep 17 00:00:00 2001 From: Mario Carneiro Date: Fri, 8 Jan 2016 20:40:06 -0500 Subject: [PATCH 5/6] maps take precedence over collections --- JSONObject.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/JSONObject.java b/JSONObject.java index e654278a5..e2e30dfaf 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -1681,6 +1681,10 @@ public static Object wrap(Object object) { return object; } + if (object instanceof Map) { + Map map = (Map) object; + return new JSONObject(map); + } if (object instanceof Collection) { Collection coll = (Collection) object; return new JSONArray(coll); @@ -1688,10 +1692,6 @@ public static Object wrap(Object object) { if (object.getClass().isArray()) { return new JSONArray(object); } - if (object instanceof Map) { - Map map = (Map) object; - return new JSONObject(map); - } Package objectPackage = object.getClass().getPackage(); String objectPackageName = objectPackage != null ? objectPackage .getName() : ""; From edfb0c57d5619bc7444364451a6d6201457136e7 Mon Sep 17 00:00:00 2001 From: Mario Carneiro Date: Wed, 20 Jul 2016 00:12:56 -0400 Subject: [PATCH 6/6] eclipse code style stuff --- CDL.java | 16 +- Cookie.java | 4 +- CookieList.java | 52 +- HTTP.java | 106 ++-- HTTPTokener.java | 27 +- JSONArray.java | 809 ++++++++++++-------------- JSONML.java | 330 +++++------ JSONObject.java | 1416 +++++++++++++++++++++------------------------- JSONTokener.java | 408 +++++++------ JSONWriter.java | 203 +++---- Property.java | 37 +- XML.java | 336 +++++------ XMLTokener.java | 358 ++++++------ 13 files changed, 1924 insertions(+), 2178 deletions(-) diff --git a/CDL.java b/CDL.java index aaa39cdda..813926d69 100644 --- a/CDL.java +++ b/CDL.java @@ -90,7 +90,7 @@ private static String getValue(JSONTokener x) throws JSONException { * Produce a JSONArray of strings from a row of comma delimited values. * @param x A JSONTokener of the source text. * @return A JSONArray of strings. - * @throws JSONException + * @throws JSONException If something goes wrong */ public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException { JSONArray ja = new JSONArray(); @@ -126,7 +126,7 @@ public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException { * method. * @param x A JSONTokener of the source text. * @return A JSONObject combining the names and values. - * @throws JSONException + * @throws JSONException If something goes wrong */ public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) throws JSONException { @@ -176,7 +176,7 @@ public static String rowToString(JSONArray ja) { * using the first row as a source of names. * @param string The comma delimited text. * @return A JSONArray of JSONObjects. - * @throws JSONException + * @throws JSONException If something goes wrong */ public static JSONArray toJSONArray(String string) throws JSONException { return toJSONArray(new JSONTokener(string)); @@ -187,7 +187,7 @@ public static JSONArray toJSONArray(String string) throws JSONException { * using the first row as a source of names. * @param x The JSONTokener containing the comma delimited text. * @return A JSONArray of JSONObjects. - * @throws JSONException + * @throws JSONException If something goes wrong */ public static JSONArray toJSONArray(JSONTokener x) throws JSONException { return toJSONArray(rowToJSONArray(x), x); @@ -199,7 +199,7 @@ public static JSONArray toJSONArray(JSONTokener x) throws JSONException { * @param names A JSONArray of strings. * @param string The comma delimited text. * @return A JSONArray of JSONObjects. - * @throws JSONException + * @throws JSONException If something goes wrong */ public static JSONArray toJSONArray(JSONArray names, String string) throws JSONException { @@ -212,7 +212,7 @@ public static JSONArray toJSONArray(JSONArray names, String string) * @param names A JSONArray of strings. * @param x A JSONTokener of the source text. * @return A JSONArray of JSONObjects. - * @throws JSONException + * @throws JSONException If something goes wrong */ public static JSONArray toJSONArray(JSONArray names, JSONTokener x) throws JSONException { @@ -240,7 +240,7 @@ public static JSONArray toJSONArray(JSONArray names, JSONTokener x) * JSONObject. * @param ja A JSONArray of JSONObjects. * @return A comma delimited text. - * @throws JSONException + * @throws JSONException If something goes wrong */ public static String toString(JSONArray ja) throws JSONException { JSONObject jo = ja.optJSONObject(0); @@ -260,7 +260,7 @@ public static String toString(JSONArray ja) throws JSONException { * @param names A JSONArray of strings. * @param ja A JSONArray of JSONObjects. * @return A comma delimited text. - * @throws JSONException + * @throws JSONException If something goes wrong */ public static String toString(JSONArray names, JSONArray ja) throws JSONException { diff --git a/Cookie.java b/Cookie.java index 348dc688d..9d8713530 100644 --- a/Cookie.java +++ b/Cookie.java @@ -76,7 +76,7 @@ public static String escape(String string) { * @param string The cookie specification string. * @return A JSONObject containing "name", "value", and possibly other * members. - * @throws JSONException + * @throws JSONException If something goes wrong */ public static JSONObject toJSONObject(String string) throws JSONException { String name; @@ -113,7 +113,7 @@ public static JSONObject toJSONObject(String string) throws JSONException { * All other members are ignored. * @param jo A JSONObject * @return A cookie specification string - * @throws JSONException + * @throws JSONException If something goes wrong */ public static String toString(JSONObject jo) throws JSONException { StringBuilder sb = new StringBuilder(); diff --git a/CookieList.java b/CookieList.java index 7a5628e91..d12edbae3 100644 --- a/CookieList.java +++ b/CookieList.java @@ -28,29 +28,31 @@ of this software and associated documentation files (the "Software"), to deal /** * Convert a web browser cookie list string to a JSONObject and back. + * * @author JSON.org * @version 2015-12-09 */ public class CookieList { /** - * Convert a cookie list into a JSONObject. A cookie list is a sequence - * of name/value pairs. The names are separated from the values by '='. - * The pairs are separated by ';'. The names and the values - * will be unescaped, possibly converting '+' and '%' sequences. - * - * To add a cookie to a cooklist, + * Convert a cookie list into a JSONObject. A cookie list is a sequence of + * name/value pairs. The names are separated from the values by '='. The + * pairs are separated by ';'. The names and the values will be unescaped, + * possibly converting '+' and '%' sequences. To add a cookie to a cooklist, * cookielistJSONObject.put(cookieJSONObject.getString("name"), - * cookieJSONObject.getString("value")); - * @param string A cookie list string + * cookieJSONObject.getString("value")); + * + * @param string A cookie list string * @return A JSONObject - * @throws JSONException + * @throws JSONException If something goes wrong */ - public static JSONObject toJSONObject(String string) throws JSONException { - JSONObject jo = new JSONObject(); - JSONTokener x = new JSONTokener(string); + public static JSONObject toJSONObject(final String string) + throws JSONException + { + final JSONObject jo = new JSONObject(); + final JSONTokener x = new JSONTokener(string); while (x.more()) { - String name = Cookie.unescape(x.nextTo('=')); + final String name = Cookie.unescape(x.nextTo('=')); x.next('='); jo.put(name, Cookie.unescape(x.nextTo(';'))); x.next(); @@ -59,25 +61,25 @@ public static JSONObject toJSONObject(String string) throws JSONException { } /** - * Convert a JSONObject into a cookie list. A cookie list is a sequence - * of name/value pairs. The names are separated from the values by '='. - * The pairs are separated by ';'. The characters '%', '+', '=', and ';' - * in the names and values are replaced by "%hh". + * Convert a JSONObject into a cookie list. A cookie list is a sequence of + * name/value pairs. The names are separated from the values by '='. The + * pairs are separated by ';'. The characters '%', '+', '=', and ';' in the + * names and values are replaced by "%hh". + * * @param jo A JSONObject * @return A cookie list string - * @throws JSONException + * @throws JSONException If something goes wrong */ - public static String toString(JSONObject jo) throws JSONException { - boolean b = false; - Iterator keys = jo.keys(); - String string; - StringBuilder sb = new StringBuilder(); + public static String toString(final JSONObject jo) throws JSONException { + boolean b = false; + final Iterator keys = jo.keys(); + String string; + final StringBuilder sb = new StringBuilder(); while (keys.hasNext()) { string = keys.next(); if (!jo.isNull(string)) { - if (b) { + if (b) sb.append(';'); - } sb.append(Cookie.escape(string)); sb.append("="); sb.append(Cookie.escape(jo.getString(string))); diff --git a/HTTP.java b/HTTP.java index b14d04ec9..4b001c173 100644 --- a/HTTP.java +++ b/HTTP.java @@ -28,6 +28,7 @@ of this software and associated documentation files (the "Software"), to deal /** * Convert an HTTP header to a JSONObject and back. + * * @author JSON.org * @version 2015-12-09 */ @@ -39,39 +40,58 @@ public class HTTP { /** * Convert an HTTP header string into a JSONObject. It can be a request * header or a response header. A request header will contain - *

{
+     * 
+     * 
+     * {
      *    Method: "POST" (for example),
      *    "Request-URI": "/" (for example),
      *    "HTTP-Version": "HTTP/1.1" (for example)
-     * }
+ * } + *
+ * * A response header will contain - *
{
+     * 
+     * 
+     * {
      *    "HTTP-Version": "HTTP/1.1" (for example),
      *    "Status-Code": "200" (for example),
      *    "Reason-Phrase": "OK" (for example)
-     * }
+ * } + *
+ * * In addition, the other parameters in the header will be captured, using - * the HTTP field names as JSON names, so that
+     * the HTTP field names as JSON names, so that
+     * 
+     * 
      *    Date: Sun, 26 May 2002 18:06:04 GMT
      *    Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
-     *    Cache-Control: no-cache
+ * Cache-Control: no-cache + *
+ * * become - *
{...
+     * 
+     * 
+     * {...
      *    Date: "Sun, 26 May 2002 18:06:04 GMT",
      *    Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
      *    "Cache-Control": "no-cache",
-     * ...}
- * It does no further checking or conversion. It does not parse dates. - * It does not do '%' transforms on URLs. + * ...} + *
+ * + * It does no further checking or conversion. It does not parse dates. It + * does not do '%' transforms on URLs. + * * @param string An HTTP header string. - * @return A JSONObject containing the elements and attributes - * of the XML string. - * @throws JSONException + * @return A JSONObject containing the elements and attributes of the XML + * string. + * @throws JSONException If something goes wrong */ - public static JSONObject toJSONObject(String string) throws JSONException { - JSONObject jo = new JSONObject(); - HTTPTokener x = new HTTPTokener(string); - String token; + public static JSONObject toJSONObject(final String string) + throws JSONException + { + final JSONObject jo = new JSONObject(); + final HTTPTokener x = new HTTPTokener(string); + String token; token = x.nextToken(); if (token.toUpperCase().startsWith("HTTP")) { @@ -83,7 +103,8 @@ public static JSONObject toJSONObject(String string) throws JSONException { jo.put("Reason-Phrase", x.nextTo('\0')); x.next(); - } else { + } + else { // Request @@ -95,7 +116,7 @@ public static JSONObject toJSONObject(String string) throws JSONException { // Fields while (x.more()) { - String name = x.nextTo(':'); + final String name = x.nextTo(':'); x.next(':'); jo.put(name, x.nextTo('\0')); x.next(); @@ -103,38 +124,46 @@ public static JSONObject toJSONObject(String string) throws JSONException { return jo; } - /** * Convert a JSONObject into an HTTP header. A request header must contain - *
{
+     * 
+     * 
+     * {
      *    Method: "POST" (for example),
      *    "Request-URI": "/" (for example),
      *    "HTTP-Version": "HTTP/1.1" (for example)
-     * }
+ * } + *
+ * * A response header must contain - *
{
+     * 
+     * 
+     * {
      *    "HTTP-Version": "HTTP/1.1" (for example),
      *    "Status-Code": "200" (for example),
      *    "Reason-Phrase": "OK" (for example)
-     * }
- * Any other members of the JSONObject will be output as HTTP fields. - * The result will end with two CRLF pairs. + * } + *
+ * + * Any other members of the JSONObject will be output as HTTP fields. The + * result will end with two CRLF pairs. + * * @param jo A JSONObject * @return An HTTP header string. - * @throws JSONException if the object does not contain enough - * information. + * @throws JSONException if the object does not contain enough information. */ - public static String toString(JSONObject jo) throws JSONException { - Iterator keys = jo.keys(); - String string; - StringBuilder sb = new StringBuilder(); + public static String toString(final JSONObject jo) throws JSONException { + final Iterator keys = jo.keys(); + String string; + final StringBuilder sb = new StringBuilder(); if (jo.has("Status-Code") && jo.has("Reason-Phrase")) { sb.append(jo.getString("HTTP-Version")); sb.append(' '); sb.append(jo.getString("Status-Code")); sb.append(' '); sb.append(jo.getString("Reason-Phrase")); - } else if (jo.has("Method") && jo.has("Request-URI")) { + } + else if (jo.has("Method") && jo.has("Request-URI")) { sb.append(jo.getString("Method")); sb.append(' '); sb.append('"'); @@ -142,15 +171,16 @@ public static String toString(JSONObject jo) throws JSONException { sb.append('"'); sb.append(' '); sb.append(jo.getString("HTTP-Version")); - } else { - throw new JSONException("Not enough material for an HTTP header."); } + else + throw new JSONException("Not enough material for an HTTP header."); sb.append(CRLF); while (keys.hasNext()) { string = keys.next(); - if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) && - !"Reason-Phrase".equals(string) && !"Method".equals(string) && - !"Request-URI".equals(string) && !jo.isNull(string)) { + if (!"HTTP-Version".equals(string) && !"Status-Code".equals(string) + && !"Reason-Phrase".equals(string) && !"Method".equals(string) + && !"Request-URI".equals(string) && !jo.isNull(string)) + { sb.append(string); sb.append(": "); sb.append(jo.getString(string)); diff --git a/HTTPTokener.java b/HTTPTokener.java index 55f48ffa5..e0255f03d 100644 --- a/HTTPTokener.java +++ b/HTTPTokener.java @@ -25,8 +25,9 @@ of this software and associated documentation files (the "Software"), to deal */ /** - * The HTTPTokener extends the JSONTokener to provide additional methods - * for the parsing of HTTP headers. + * The HTTPTokener extends the JSONTokener to provide additional methods for the + * parsing of HTTP headers. + * * @author JSON.org * @version 2015-12-09 */ @@ -34,42 +35,40 @@ public class HTTPTokener extends JSONTokener { /** * Construct an HTTPTokener from a string. + * * @param string A source string. */ - public HTTPTokener(String string) { + public HTTPTokener(final String string) { super(string); } - /** * Get the next token or string. This is used in parsing HTTP headers. - * @throws JSONException + * + * @throws JSONException If something goes wrong * @return A String. */ public String nextToken() throws JSONException { char c; char q; - StringBuilder sb = new StringBuilder(); - do { + final StringBuilder sb = new StringBuilder(); + do c = next(); - } while (Character.isWhitespace(c)); + while (Character.isWhitespace(c)); if (c == '"' || c == '\'') { q = c; for (;;) { c = next(); - if (c < ' ') { + if (c < ' ') throw syntaxError("Unterminated string."); - } - if (c == q) { + if (c == q) return sb.toString(); - } sb.append(c); } } for (;;) { - if (c == 0 || Character.isWhitespace(c)) { + if (c == 0 || Character.isWhitespace(c)) return sb.toString(); - } sb.append(c); c = next(); } diff --git a/JSONArray.java b/JSONArray.java index 15487e0e2..b813560af 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -23,16 +23,11 @@ of this software and associated documentation files (the "Software"), to deal OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; +import java.io.*; import java.lang.reflect.Array; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; +import java.util.*; /** * A JSONArray is an ordered sequence of values. Its external text form is a @@ -70,8 +65,8 @@ of this software and associated documentation files (the "Software"), to deal *
  • Strings do not need to be quoted at all if they do not begin with a quote * or single quote, and if they do not contain leading or trailing spaces, and * if they do not contain any of these characters: - * { } [ ] / \ : , # and if they do not look like numbers and - * if they are not the reserved words true, false, or + * { } [ ] / \ : , # and if they do not look like numbers and if + * they are not the reserved words true, false, or * null.
  • * * @@ -90,37 +85,34 @@ public JSONArray() { /** * Construct a JSONArray from a JSONTokener. * - * @param x - * A JSONTokener - * @throws JSONException - * If there is a syntax error. + * @param x A JSONTokener + * @throws JSONException If there is a syntax error. */ - public JSONArray(JSONTokener x) throws JSONException { + public JSONArray(final JSONTokener x) throws JSONException { this(); - if (x.nextClean() != '[') { + if (x.nextClean() != '[') throw x.syntaxError("A JSONArray text must start with '['"); - } if (x.nextClean() != ']') { x.back(); for (;;) { if (x.nextClean() == ',') { x.back(); super.add(JSONObject.NULL); - } else { + } + else { x.back(); super.add(x.nextValue()); } switch (x.nextClean()) { - case ',': - if (x.nextClean() == ']') { + case ',': + if (x.nextClean() == ']') + return; + x.back(); + break; + case ']': return; - } - x.back(); - break; - case ']': - return; - default: - throw x.syntaxError("Expected a ',' or ']'"); + default: + throw x.syntaxError("Expected a ',' or ']'"); } } } @@ -129,77 +121,70 @@ public JSONArray(JSONTokener x) throws JSONException { /** * Construct a JSONArray from a source JSON text. * - * @param source - * A string that begins with [ (left - * bracket) and ends with ] - *  (right bracket). - * @throws JSONException - * If there is a syntax error. + * @param source A string that begins with [ (left + * bracket) and ends with ]   + * (right bracket). + * @throws JSONException If there is a syntax error. */ - public JSONArray(String source) throws JSONException { + public JSONArray(final String source) throws JSONException { this(new JSONTokener(source)); } /** * Construct a JSONArray from a Collection. * - * @param collection - * A Collection. + * @param collection A Collection. */ - public JSONArray(Collection collection) { + public JSONArray(final Collection collection) { this(); - if (collection != null) { - for (Object o: collection){ + if (collection != null) + for (final Object o : collection) super.add(JSONObject.wrap(o)); - } - } } /** * Construct a JSONArray from an array + * * @param The type of the array elements + * @param array The array */ @SafeVarargs - public JSONArray(T... array) { + public JSONArray(final T... array) { this(); - for (T x : array) { + for (final T x : array) this.put(JSONObject.wrap(x)); - } } /** * Construct a JSONArray from an array * - * @throws JSONException - * If not an array. + * @param array The array + * @throws JSONException If not an array. */ - public JSONArray(Object array) throws JSONException { + public JSONArray(final Object array) throws JSONException { this(); if (array.getClass().isArray()) { - int length = Array.getLength(array); - for (int i = 0; i < length; i += 1) { + final int length = Array.getLength(array); + for (int i = 0; i < length; i += 1) this.put(JSONObject.wrap(Array.get(array, i))); - } - } else { - throw new JSONException( - "JSONArray initial value should be a string or collection or array."); } + else + throw new JSONException( + "JSONArray initial value should be a string or collection or array."); } /** * Get the object value associated with an index. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return An object value. - * @throws JSONException - * If there is no value for the index. + * @throws JSONException If there is no value for the index. */ - public Object get(int index) throws JSONException { - Object object = this.opt(index); - if (object == null) { + @Override + public Object get(final int index) throws JSONException { + final Object object = opt(index); + if (object == null) throw new JSONException("JSONArray[" + index + "] not found."); - } return object; } @@ -207,213 +192,193 @@ public Object get(int index) throws JSONException { * Get the boolean value associated with an index. The string values "true" * and "false" are converted to boolean. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return The truth. - * @throws JSONException - * If there is no value for the index or if the value is not - * convertible to boolean. + * @throws JSONException If there is no value for the index or if the value + * is not convertible to boolean. */ - public boolean getBoolean(int index) throws JSONException { - Object object = this.get(index); - if (object.equals(Boolean.FALSE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("false"))) { + public boolean getBoolean(final int index) throws JSONException { + final Object object = get(index); + if (object.equals(Boolean.FALSE) || object instanceof String + && ((String)object).equalsIgnoreCase("false")) return false; - } else if (object.equals(Boolean.TRUE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("true"))) { + else if (object.equals(Boolean.TRUE) || object instanceof String + && ((String)object).equalsIgnoreCase("true")) return true; - } throw new JSONException("JSONArray[" + index + "] is not a boolean."); } /** * Get the double value associated with an index. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a number. + * @throws JSONException If the key is not found or if the value cannot be + * converted to a number. */ - public double getDouble(int index) throws JSONException { - Object object = this.get(index); + public double getDouble(final int index) throws JSONException { + final Object object = get(index); try { - return object instanceof Number ? ((Number) object).doubleValue() - : Double.parseDouble((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number."); + return object instanceof Number ? ((Number)object).doubleValue() + : Double.parseDouble((String)object); + } catch (final Exception e) { + throw new JSONException( + "JSONArray[" + index + "] is not a number."); } } /** - * Get the enum value associated with an index. - * - * @param clazz - * The type of enum to retrieve. - * @param index - * The index must be between 0 and length() - 1. - * @return The enum value at the index location - * @throws JSONException - * if the key is not found or if the value cannot be converted - * to an enum. - */ - public > E getEnum(Class clazz, int index) throws JSONException { - E val = optEnum(clazz, index); - if(val==null) { + * Get the enum value associated with an index. + * + * @param The enum type + * @param clazz The type of enum to retrieve. + * @param index The index must be between 0 and length() - 1. + * @return The enum value at the index location + * @throws JSONException if the key is not found or if the value cannot be + * converted to an enum. + */ + public > E getEnum(final Class clazz, final int index) + throws JSONException + { + final E val = optEnum(clazz, index); + if (val == null) // JSONException should really take a throwable argument. // If it did, I would re-implement this with the Enum.valueOf // method and place any thrown exception in the JSONException - throw new JSONException("JSONObject[" + JSONObject.quote(Integer.toString(index)) - + "] is not an enum of type " + JSONObject.quote(clazz.getSimpleName()) - + "."); - } + throw new JSONException( + "JSONObject[" + JSONObject.quote(Integer.toString(index)) + + "] is not an enum of type " + + JSONObject.quote(clazz.getSimpleName()) + "."); return val; } /** * Get the BigDecimal value associated with an index. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a BigDecimal. + * @throws JSONException If the key is not found or if the value cannot be + * converted to a BigDecimal. */ - public BigDecimal getBigDecimal (int index) throws JSONException { - Object object = this.get(index); + public BigDecimal getBigDecimal(final int index) throws JSONException { + final Object object = get(index); try { return new BigDecimal(object.toString()); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] could not convert to BigDecimal."); + } catch (final Exception e) { + throw new JSONException( + "JSONArray[" + index + "] could not convert to BigDecimal."); } } /** * Get the BigInteger value associated with an index. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a BigInteger. + * @throws JSONException If the key is not found or if the value cannot be + * converted to a BigInteger. */ - public BigInteger getBigInteger (int index) throws JSONException { - Object object = this.get(index); + public BigInteger getBigInteger(final int index) throws JSONException { + final Object object = get(index); try { return new BigInteger(object.toString()); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + - "] could not convert to BigInteger."); + } catch (final Exception e) { + throw new JSONException( + "JSONArray[" + index + "] could not convert to BigInteger."); } } /** * Get the int value associated with an index. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return The value. - * @throws JSONException - * If the key is not found or if the value is not a number. + * @throws JSONException If the key is not found or if the value is not a + * number. */ - public int getInt(int index) throws JSONException { - Object object = this.get(index); + public int getInt(final int index) throws JSONException { + final Object object = get(index); try { - return object instanceof Number ? ((Number) object).intValue() - : Integer.parseInt((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number."); + return object instanceof Number ? ((Number)object).intValue() + : Integer.parseInt((String)object); + } catch (final Exception e) { + throw new JSONException( + "JSONArray[" + index + "] is not a number."); } } /** * Get the JSONArray associated with an index. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return A JSONArray value. - * @throws JSONException - * If there is no value for the index. or if the value is not a - * JSONArray + * @throws JSONException If there is no value for the index. or if the value + * is not a JSONArray */ - public JSONArray getJSONArray(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONArray) { - return (JSONArray) object; - } + public JSONArray getJSONArray(final int index) throws JSONException { + final Object object = get(index); + if (object instanceof JSONArray) + return (JSONArray)object; throw new JSONException("JSONArray[" + index + "] is not a JSONArray."); } /** * Get the JSONObject associated with an index. * - * @param index - * subscript + * @param index subscript * @return A JSONObject value. - * @throws JSONException - * If there is no value for the index or if the value is not a - * JSONObject + * @throws JSONException If there is no value for the index or if the value + * is not a JSONObject */ - public JSONObject getJSONObject(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof JSONObject) { - return (JSONObject) object; - } - throw new JSONException("JSONArray[" + index + "] is not a JSONObject."); + public JSONObject getJSONObject(final int index) throws JSONException { + final Object object = get(index); + if (object instanceof JSONObject) + return (JSONObject)object; + throw new JSONException( + "JSONArray[" + index + "] is not a JSONObject."); } /** * Get the long value associated with an index. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return The value. - * @throws JSONException - * If the key is not found or if the value cannot be converted - * to a number. + * @throws JSONException If the key is not found or if the value cannot be + * converted to a number. */ - public long getLong(int index) throws JSONException { - Object object = this.get(index); + public long getLong(final int index) throws JSONException { + final Object object = get(index); try { - return object instanceof Number ? ((Number) object).longValue() - : Long.parseLong((String) object); - } catch (Exception e) { - throw new JSONException("JSONArray[" + index + "] is not a number."); + return object instanceof Number ? ((Number)object).longValue() + : Long.parseLong((String)object); + } catch (final Exception e) { + throw new JSONException( + "JSONArray[" + index + "] is not a number."); } } /** * Get the string associated with an index. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return A string value. - * @throws JSONException - * If there is no string value for the index. + * @throws JSONException If there is no string value for the index. */ - public String getString(int index) throws JSONException { - Object object = this.get(index); - if (object instanceof String) { - return (String) object; - } + public String getString(final int index) throws JSONException { + final Object object = get(index); + if (object instanceof String) + return (String)object; throw new JSONException("JSONArray[" + index + "] not a string."); } /** * Determine if the value is null. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return true if the value at the index is null, or if there is no value. */ - public boolean isNull(int index) { - return JSONObject.NULL.equals(this.opt(index)); + public boolean isNull(final int index) { + return JSONObject.NULL.equals(opt(index)); } /** @@ -421,20 +386,17 @@ public boolean isNull(int index) { * separator string is inserted between each element. Warning: * This method assumes that the data structure is acyclical. * - * @param separator - * A string that will be inserted between the elements. + * @param separator A string that will be inserted between the elements. * @return a string. - * @throws JSONException - * If the array contains an invalid number. + * @throws JSONException If the array contains an invalid number. */ - public String join(String separator) throws JSONException { - int len = this.length(); - StringBuilder sb = new StringBuilder(); + public String join(final String separator) throws JSONException { + final int len = length(); + final StringBuilder sb = new StringBuilder(); for (int i = 0; i < len; i += 1) { - if (i > 0) { + if (i > 0) sb.append(separator); - } sb.append(JSONObject.valueToString(super.get(i))); } return sb.toString(); @@ -452,12 +414,11 @@ public int length() { /** * Get the optional object value associated with an index. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return An object value, or null if there is no object at that index. */ - public Object opt(int index) { - return (index < 0 || index >= this.length()) ? null : super.get(index); + public Object opt(final int index) { + return index < 0 || index >= length() ? null : super.get(index); } /** @@ -465,11 +426,10 @@ public Object opt(int index) { * if there is no value at that index, or if the value is not Boolean.TRUE * or the String "true". * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return The truth. */ - public boolean optBoolean(int index) { + public boolean optBoolean(final int index) { return this.optBoolean(index, false); } @@ -478,16 +438,14 @@ public boolean optBoolean(int index) { * defaultValue if there is no value at that index or if it is not a Boolean * or the String "true" or "false" (case insensitive). * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * A boolean default. + * @param index The index must be between 0 and length() - 1. + * @param defaultValue A boolean default. * @return The truth. */ - public boolean optBoolean(int index, boolean defaultValue) { + public boolean optBoolean(final int index, final boolean defaultValue) { try { - return this.getBoolean(index); - } catch (Exception e) { + return getBoolean(index); + } catch (final Exception e) { return defaultValue; } } @@ -497,11 +455,10 @@ public boolean optBoolean(int index, boolean defaultValue) { * if there is no value for the index, or if the value is not a number and * cannot be converted to a number. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return The value. */ - public double optDouble(int index) { + public double optDouble(final int index) { return this.optDouble(index, Double.NaN); } @@ -510,16 +467,14 @@ public double optDouble(int index) { * is returned if there is no value for the index, or if the value is not a * number and cannot be converted to a number. * - * @param index - * subscript - * @param defaultValue - * The default value. + * @param index subscript + * @param defaultValue The default value. * @return The value. */ - public double optDouble(int index, double defaultValue) { + public double optDouble(final int index, final double defaultValue) { try { - return this.getDouble(index); - } catch (Exception e) { + return getDouble(index); + } catch (final Exception e) { return defaultValue; } } @@ -529,11 +484,10 @@ public double optDouble(int index, double defaultValue) { * there is no value for the index, or if the value is not a number and * cannot be converted to a number. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return The value. */ - public int optInt(int index) { + public int optInt(final int index) { return this.optInt(index, 0); } @@ -542,55 +496,53 @@ public int optInt(int index) { * returned if there is no value for the index, or if the value is not a * number and cannot be converted to a number. * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. + * @param index The index must be between 0 and length() - 1. + * @param defaultValue The default value. * @return The value. */ - public int optInt(int index, int defaultValue) { + public int optInt(final int index, final int defaultValue) { try { - return this.getInt(index); - } catch (Exception e) { + return getInt(index); + } catch (final Exception e) { return defaultValue; } } /** * Get the enum value associated with a key. - * - * @param clazz - * The type of enum to retrieve. - * @param index - * The index must be between 0 and length() - 1. + * + * @param The enum + * @param clazz The type of enum to retrieve. + * @param index The index must be between 0 and length() - 1. * @return The enum value at the index location or null if not found */ - public > E optEnum(Class clazz, int index) { + public > E optEnum(final Class clazz, + final int index) + { return this.optEnum(clazz, index, null); } /** * Get the enum value associated with a key. - * - * @param clazz - * The type of enum to retrieve. - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default in case the value is not found - * @return The enum value at the index location or defaultValue if - * the value is not found or cannot be assigned to clazz + * + * @param The enum type + * @param clazz The type of enum to retrieve. + * @param index The index must be between 0 and length() - 1. + * @param defaultValue The default in case the value is not found + * @return The enum value at the index location or defaultValue if the value + * is not found or cannot be assigned to clazz */ - public > E optEnum(Class clazz, int index, E defaultValue) { + public > E optEnum(final Class clazz, final int index, + final E defaultValue) + { try { - Object val = this.opt(index); - if (JSONObject.NULL.equals(val)) { + final Object val = opt(index); + if (JSONObject.NULL.equals(val)) return defaultValue; - } if (clazz.isAssignableFrom(val.getClass())) { // we just checked it! @SuppressWarnings("unchecked") - E myE = (E) val; + final E myE = (E)val; return myE; } return Enum.valueOf(clazz, val.toString()); @@ -599,41 +551,40 @@ public > E optEnum(Class clazz, int index, E defaultValue) } } - /** - * Get the optional BigInteger value associated with an index. The - * defaultValue is returned if there is no value for the index, or if the + * Get the optional BigInteger value associated with an index. The + * defaultValue is returned if there is no value for the index, or if the * value is not a number and cannot be converted to a number. * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. + * @param index The index must be between 0 and length() - 1. + * @param defaultValue The default value. * @return The value. */ - public BigInteger optBigInteger(int index, BigInteger defaultValue) { + public BigInteger optBigInteger(final int index, + final BigInteger defaultValue) + { try { - return this.getBigInteger(index); - } catch (Exception e) { + return getBigInteger(index); + } catch (final Exception e) { return defaultValue; } } /** - * Get the optional BigDecimal value associated with an index. The - * defaultValue is returned if there is no value for the index, or if the + * Get the optional BigDecimal value associated with an index. The + * defaultValue is returned if there is no value for the index, or if the * value is not a number and cannot be converted to a number. * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. + * @param index The index must be between 0 and length() - 1. + * @param defaultValue The default value. * @return The value. */ - public BigDecimal optBigDecimal(int index, BigDecimal defaultValue) { + public BigDecimal optBigDecimal(final int index, + final BigDecimal defaultValue) + { try { - return this.getBigDecimal(index); - } catch (Exception e) { + return getBigDecimal(index); + } catch (final Exception e) { return defaultValue; } } @@ -641,14 +592,13 @@ public BigDecimal optBigDecimal(int index, BigDecimal defaultValue) { /** * Get the optional JSONArray associated with an index. * - * @param index - * subscript + * @param index subscript * @return A JSONArray value, or null if the index has no value, or if the * value is not a JSONArray. */ - public JSONArray optJSONArray(int index) { - Object o = this.opt(index); - return o instanceof JSONArray ? (JSONArray) o : null; + public JSONArray optJSONArray(final int index) { + final Object o = opt(index); + return o instanceof JSONArray ? (JSONArray)o : null; } /** @@ -656,13 +606,12 @@ public JSONArray optJSONArray(int index) { * the key is not found, or null if the index has no value, or if the value * is not a JSONObject. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return A JSONObject value. */ - public JSONObject optJSONObject(int index) { - Object o = this.opt(index); - return o instanceof JSONObject ? (JSONObject) o : null; + public JSONObject optJSONObject(final int index) { + final Object o = opt(index); + return o instanceof JSONObject ? (JSONObject)o : null; } /** @@ -670,11 +619,10 @@ public JSONObject optJSONObject(int index) { * there is no value for the index, or if the value is not a number and * cannot be converted to a number. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return The value. */ - public long optLong(int index) { + public long optLong(final int index) { return this.optLong(index, 0); } @@ -683,16 +631,14 @@ public long optLong(int index) { * returned if there is no value for the index, or if the value is not a * number and cannot be converted to a number. * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. + * @param index The index must be between 0 and length() - 1. + * @param defaultValue The default value. * @return The value. */ - public long optLong(int index, long defaultValue) { + public long optLong(final int index, final long defaultValue) { try { - return this.getLong(index); - } catch (Exception e) { + return getLong(index); + } catch (final Exception e) { return defaultValue; } } @@ -702,11 +648,10 @@ public long optLong(int index, long defaultValue) { * empty string if there is no value at that index. If the value is not a * string and is not null, then it is coverted to a string. * - * @param index - * The index must be between 0 and length() - 1. + * @param index The index must be between 0 and length() - 1. * @return A String value. */ - public String optString(int index) { + public String optString(final int index) { return this.optString(index, ""); } @@ -714,26 +659,23 @@ public String optString(int index) { * Get the optional string associated with an index. The defaultValue is * returned if the key is not found. * - * @param index - * The index must be between 0 and length() - 1. - * @param defaultValue - * The default value. + * @param index The index must be between 0 and length() - 1. + * @param defaultValue The default value. * @return A String value. */ - public String optString(int index, String defaultValue) { - Object object = this.opt(index); - return JSONObject.NULL.equals(object) ? defaultValue : object - .toString(); + public String optString(final int index, final String defaultValue) { + final Object object = opt(index); + return JSONObject.NULL.equals(object) ? defaultValue + : object.toString(); } /** * Append a boolean value. This increases the array's length by one. * - * @param value - * A boolean value. + * @param value A boolean value. * @return this. */ - public JSONArray put(boolean value) { + public JSONArray put(final boolean value) { this.put(value ? Boolean.TRUE : Boolean.FALSE); return this; } @@ -742,25 +684,23 @@ public JSONArray put(boolean value) { * Put a value in the JSONArray, where the value will be a JSONArray which * is produced from a Collection. * - * @param value - * A Collection value. + * @param value A Collection value. * @return this. */ - public JSONArray put(Collection value) { - return put((Object) (value instanceof JSONArray ? value : new JSONArray(value))); + public JSONArray put(final Collection value) { + return put((Object)(value instanceof JSONArray ? value + : new JSONArray(value))); } /** * Append a double value. This increases the array's length by one. * - * @param value - * A double value. - * @throws JSONException - * if the value is not finite. + * @param value A double value. + * @throws JSONException if the value is not finite. * @return this. */ - public JSONArray put(double value) throws JSONException { - Double d = new Double(value); + public JSONArray put(final double value) throws JSONException { + final Double d = new Double(value); JSONObject.testValidity(d); this.put(d); return this; @@ -769,11 +709,10 @@ public JSONArray put(double value) throws JSONException { /** * Append an int value. This increases the array's length by one. * - * @param value - * An int value. + * @param value An int value. * @return this. */ - public JSONArray put(int value) { + public JSONArray put(final int value) { this.put(new Integer(value)); return this; } @@ -781,11 +720,10 @@ public JSONArray put(int value) { /** * Append an long value. This increases the array's length by one. * - * @param value - * A long value. + * @param value A long value. * @return this. */ - public JSONArray put(long value) { + public JSONArray put(final long value) { this.put(new Long(value)); return this; } @@ -794,24 +732,23 @@ public JSONArray put(long value) { * Put a value in the JSONArray, where the value will be a JSONObject which * is produced from a Map. * - * @param value - * A Map value. + * @param value A Map value. * @return this. */ - public JSONArray put(Map value) { - return put((Object) (value instanceof JSONObject ? value : new JSONObject(value))); + public JSONArray put(final Map value) { + return put((Object)(value instanceof JSONObject ? value + : new JSONObject(value))); } /** * Append an object value. This increases the array's length by one. * - * @param value - * An object value. The value should be a Boolean, Double, + * @param value An object value. The value should be a Boolean, Double, * Integer, JSONArray, JSONObject, Long, or String, or the * JSONObject.NULL object. * @return this. */ - public JSONArray put(Object value) { + public JSONArray put(final Object value) { super.add(value); return this; } @@ -821,15 +758,14 @@ public JSONArray put(Object value) { * than the length of the JSONArray, then null elements will be added as * necessary to pad it out. * - * @param index - * The subscript. - * @param value - * A boolean value. + * @param index The subscript. + * @param value A boolean value. * @return this. - * @throws JSONException - * If the index is negative. + * @throws JSONException If the index is negative. */ - public JSONArray put(int index, boolean value) throws JSONException { + public JSONArray put(final int index, final boolean value) + throws JSONException + { this.put(index, value ? Boolean.TRUE : Boolean.FALSE); return this; } @@ -838,16 +774,17 @@ public JSONArray put(int index, boolean value) throws JSONException { * Put a value in the JSONArray, where the value will be a JSONArray which * is produced from a Collection. * - * @param index - * The subscript. - * @param value - * A Collection value. + * @param index The subscript. + * @param value A Collection value. * @return this. - * @throws JSONException - * If the index is negative or if the value is not finite. + * @throws JSONException If the index is negative or if the value is not + * finite. */ - public JSONArray put(int index, Collection value) throws JSONException { - return put(index, (Object) (value instanceof JSONArray ? value : new JSONArray(value))); + public JSONArray put(final int index, final Collection value) + throws JSONException + { + return put(index, (Object)(value instanceof JSONArray ? value + : new JSONArray(value))); } /** @@ -855,15 +792,15 @@ public JSONArray put(int index, Collection value) throws JSONException { * the JSONArray, then null elements will be added as necessary to pad it * out. * - * @param index - * The subscript. - * @param value - * A double value. + * @param index The subscript. + * @param value A double value. * @return this. - * @throws JSONException - * If the index is negative or if the value is not finite. + * @throws JSONException If the index is negative or if the value is not + * finite. */ - public JSONArray put(int index, double value) throws JSONException { + public JSONArray put(final int index, final double value) + throws JSONException + { this.put(index, new Double(value)); return this; } @@ -873,15 +810,14 @@ public JSONArray put(int index, double value) throws JSONException { * the JSONArray, then null elements will be added as necessary to pad it * out. * - * @param index - * The subscript. - * @param value - * An int value. + * @param index The subscript. + * @param value An int value. * @return this. - * @throws JSONException - * If the index is negative. + * @throws JSONException If the index is negative. */ - public JSONArray put(int index, int value) throws JSONException { + public JSONArray put(final int index, final int value) + throws JSONException + { this.put(index, new Integer(value)); return this; } @@ -891,15 +827,14 @@ public JSONArray put(int index, int value) throws JSONException { * the JSONArray, then null elements will be added as necessary to pad it * out. * - * @param index - * The subscript. - * @param value - * A long value. + * @param index The subscript. + * @param value A long value. * @return this. - * @throws JSONException - * If the index is negative. + * @throws JSONException If the index is negative. */ - public JSONArray put(int index, long value) throws JSONException { + public JSONArray put(final int index, final long value) + throws JSONException + { this.put(index, new Long(value)); return this; } @@ -908,17 +843,17 @@ public JSONArray put(int index, long value) throws JSONException { * Put a value in the JSONArray, where the value will be a JSONObject that * is produced from a Map. * - * @param index - * The subscript. - * @param value - * The Map value. + * @param index The subscript. + * @param value The Map value. * @return this. - * @throws JSONException - * If the index is negative or if the the value is an invalid - * number. + * @throws JSONException If the index is negative or if the the value is an + * invalid number. */ - public JSONArray put(int index, Map value) throws JSONException { - return put(index, (Object) (value instanceof JSONObject ? value : new JSONObject(value))); + public JSONArray put(final int index, final Map value) + throws JSONException + { + return put(index, (Object)(value instanceof JSONObject ? value + : new JSONObject(value))); } /** @@ -926,28 +861,25 @@ public JSONArray put(int index, Map value) throws JSONException { * than the length of the JSONArray, then null elements will be added as * necessary to pad it out. * - * @param index - * The subscript. - * @param value - * The value to put into the array. The value should be a + * @param index The subscript. + * @param value The value to put into the array. The value should be a * Boolean, Double, Integer, JSONArray, JSONObject, Long, or * String, or the JSONObject.NULL object. * @return this. - * @throws JSONException - * If the index is negative or if the the value is an invalid - * number. + * @throws JSONException If the index is negative or if the the value is an + * invalid number. */ - public JSONArray put(int index, Object value) throws JSONException { + public JSONArray put(final int index, final Object value) + throws JSONException + { JSONObject.testValidity(value); - if (index < 0) { + if (index < 0) throw new JSONException("JSONArray[" + index + "] not found."); - } - if (index < this.length()) { + if (index < length()) super.set(index, value); - } else { - while (index != this.length()) { + else { + while (index != length()) this.put(JSONObject.NULL); - } this.put(value); } return this; @@ -956,46 +888,41 @@ public JSONArray put(int index, Object value) throws JSONException { /** * Remove an index and close the hole. * - * @param index - * The index of the element to be removed. + * @param index The index of the element to be removed. * @return The value that was associated with the index, or null if there * was no value. */ - public Object remove(int index) { - return index >= 0 && index < this.length() - ? super.remove(index) - : null; + @Override + public Object remove(final int index) { + return index >= 0 && index < length() ? super.remove(index) : null; } /** - * Determine if two JSONArrays are similar. - * They must contain similar sequences. + * Determine if two JSONArrays are similar. They must contain similar + * sequences. * * @param other The other JSONArray * @return true if they are equal */ - public boolean similar(Object other) { - if (!(other instanceof JSONArray)) { + public boolean similar(final Object other) { + if (!(other instanceof JSONArray)) return false; - } - int len = this.length(); - if (len != ((JSONArray)other).length()) { + final int len = length(); + if (len != ((JSONArray)other).length()) return false; - } for (int i = 0; i < len; i += 1) { - Object valueThis = this.get(i); - Object valueOther = ((JSONArray)other).get(i); + final Object valueThis = get(i); + final Object valueOther = ((JSONArray)other).get(i); if (valueThis instanceof JSONObject) { - if (!((JSONObject)valueThis).similar(valueOther)) { + if (!((JSONObject)valueThis).similar(valueOther)) return false; - } - } else if (valueThis instanceof JSONArray) { - if (!((JSONArray)valueThis).similar(valueOther)) { + } + else if (valueThis instanceof JSONArray) { + if (!((JSONArray)valueThis).similar(valueOther)) return false; - } - } else if (!valueThis.equals(valueOther)) { - return false; } + else if (!valueThis.equals(valueOther)) + return false; } return true; } @@ -1004,22 +931,18 @@ public boolean similar(Object other) { * Produce a JSONObject by combining a JSONArray of names with the values of * this JSONArray. * - * @param names - * A JSONArray containing a list of key strings. These will be + * @param names A JSONArray containing a list of key strings. These will be * paired with the values. * @return A JSONObject, or null if there are no names or if this JSONArray * has no values. - * @throws JSONException - * If any of the names are null. + * @throws JSONException If any of the names are null. */ - public JSONObject toJSONObject(JSONArray names) throws JSONException { - if (names == null || names.length() == 0 || this.length() == 0) { + public JSONObject toJSONObject(final JSONArray names) throws JSONException { + if (names == null || names.length() == 0 || length() == 0) return null; - } - JSONObject jo = new JSONObject(); - for (int i = 0; i < names.length(); i += 1) { - jo.put(names.getString(i), this.opt(i)); - } + final JSONObject jo = new JSONObject(); + for (int i = 0; i < names.length(); i += 1) + jo.put(names.getString(i), opt(i)); return jo; } @@ -1034,10 +957,11 @@ public JSONObject toJSONObject(JSONArray names) throws JSONException { * @return a printable, displayable, transmittable representation of the * array. */ + @Override public String toString() { try { return this.toString(0); - } catch (Exception e) { + } catch (final Exception e) { return null; } } @@ -1046,16 +970,16 @@ public String toString() { * Make a prettyprinted JSON text of this JSONArray. Warning: This method * assumes that the data structure is acyclical. * - * @param indentFactor - * The number of spaces to add to each level of indentation. + * @param indentFactor The number of spaces to add to each level of + * indentation. * @return a printable, displayable, transmittable representation of the * object, beginning with [ (left - * bracket) and ending with ] - *  (right bracket). - * @throws JSONException + * bracket) and ending with ]   + * (right bracket). + * @throws JSONException If something goes wrong */ - public String toString(int indentFactor) throws JSONException { - StringWriter sw = new StringWriter(); + public String toString(final int indentFactor) throws JSONException { + final StringWriter sw = new StringWriter(); synchronized (sw.getBuffer()) { return this.write(sw, indentFactor, 0).toString(); } @@ -1066,11 +990,12 @@ public String toString(int indentFactor) throws JSONException { * compactness, no whitespace is added. *

    * Warning: This method assumes that the data structure is acyclical. - * + * + * @param writer The writer * @return The writer. - * @throws JSONException + * @throws JSONException If something goes wrong */ - public Writer write(Writer writer) throws JSONException { + public Writer write(final Writer writer) throws JSONException { return this.write(writer, 0, 0); } @@ -1080,48 +1005,44 @@ public Writer write(Writer writer) throws JSONException { *

    * Warning: This method assumes that the data structure is acyclical. * - * @param writer - * Writes the serialized JSON - * @param indentFactor - * The number of spaces to add to each level of indentation. - * @param indent - * The indention of the top level. + * @param writer Writes the serialized JSON + * @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 + * @throws JSONException If something goes wrong */ - public Writer write(Writer writer, int indentFactor, int indent) - throws JSONException { + public Writer write(final Writer writer, final int indentFactor, + final int indent) throws JSONException + { try { boolean commanate = false; - int length = this.length(); + final int length = length(); writer.write('['); - if (length == 1) { - JSONObject.writeValue(writer, super.get(0), - indentFactor, indent); - } else if (length != 0) { + if (length == 1) + JSONObject.writeValue(writer, super.get(0), indentFactor, + indent); + else if (length != 0) { final int newindent = indent + indentFactor; for (int i = 0; i < length; i += 1) { - if (commanate) { + if (commanate) writer.write(','); - } - if (indentFactor > 0) { + if (indentFactor > 0) writer.write('\n'); - } JSONObject.indent(writer, newindent); - JSONObject.writeValue(writer, super.get(i), - indentFactor, newindent); + JSONObject.writeValue(writer, super.get(i), indentFactor, + newindent); commanate = true; } - if (indentFactor > 0) { + if (indentFactor > 0) writer.write('\n'); - } JSONObject.indent(writer, indent); } writer.write(']'); return writer; - } catch (IOException e) { + } catch (final IOException e) { throw new JSONException(e); } } diff --git a/JSONML.java b/JSONML.java index a4b874dd5..342c964a4 100644 --- a/JSONML.java +++ b/JSONML.java @@ -26,7 +26,6 @@ of this software and associated documentation files (the "Software"), to deal import java.util.Iterator; - /** * This provides static methods to convert an XML text into a JSONArray or * JSONObject, and to covert a JSONArray or JSONObject into an XML text using @@ -39,26 +38,25 @@ public class JSONML { /** * Parse XML values and store them in a JSONArray. - * @param x The XMLTokener containing the source string. + * + * @param x The XMLTokener containing the source string. * @param arrayForm true if array form, false if object form. - * @param ja The JSONArray that is containing the current tag or null - * if we are at the outermost level. + * @param ja The JSONArray that is containing the current tag or null if we + * are at the outermost level. * @return A JSONArray if the value is the outermost tag, otherwise null. - * @throws JSONException + * @throws JSONException If something goes wrong */ - private static Object parse( - XMLTokener x, - boolean arrayForm, - JSONArray ja - ) throws JSONException { - String attribute; - char c; - String closeTag = null; - int i; - JSONArray newja = null; + private static Object parse(final XMLTokener x, final boolean arrayForm, + final JSONArray ja) throws JSONException + { + String attribute; + char c; + String closeTag = null; + int i; + JSONArray newja = null; JSONObject newjo = null; - Object token; - String tagName = null; + Object token; + String tagName = null; // Test for and skip past these forms: // @@ -67,9 +65,8 @@ private static Object parse( // while (true) { - if (!x.more()) { + if (!x.more()) throw x.syntaxError("Bad XML"); - } token = x.nextContent(); if (token == XML.LT) { token = x.nextToken(); @@ -79,248 +76,235 @@ private static Object parse( // Close tag "); - } else { + else x.back(); - } - } else if (c == '[') { + } + else if (c == '[') { token = x.nextToken(); if (token.equals("CDATA") && x.next() == '[') { - if (ja != null) { + if (ja != null) ja.put(x.nextCDATA()); - } - } else { - throw x.syntaxError("Expected 'CDATA['"); } - } else { + else + throw x.syntaxError("Expected 'CDATA['"); + } + else { i = 1; do { token = x.nextMeta(); - if (token == null) { - throw x.syntaxError("Missing '>' after '' after ' 0); } - } else if (token == XML.QUEST) { - -// "); - } else { + else throw x.syntaxError("Misshaped tag"); - } // Open tag < - } else { - if (!(token instanceof String)) { + } + else { + if (!(token instanceof String)) throw x.syntaxError("Bad tagName '" + token + "'."); - } tagName = (String)token; newja = new JSONArray(); newjo = new JSONObject(); if (arrayForm) { newja.put(tagName); - if (ja != null) { + if (ja != null) ja.put(newja); - } - } else { + } + else { newjo.put("tagName", tagName); - if (ja != null) { + if (ja != null) ja.put(newjo); - } } token = null; for (;;) { - if (token == null) { + if (token == null) token = x.nextToken(); - } - if (token == null) { + if (token == null) throw x.syntaxError("Misshaped tag"); - } - if (!(token instanceof String)) { + if (!(token instanceof String)) break; - } // attribute = value attribute = (String)token; - if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) { + if (!arrayForm && ("tagName".equals(attribute) + || "childNode".equals(attribute))) throw x.syntaxError("Reserved attribute."); - } token = x.nextToken(); if (token == XML.EQ) { token = x.nextToken(); - if (!(token instanceof String)) { + if (!(token instanceof String)) throw x.syntaxError("Missing value"); - } - newjo.accumulate(attribute, XML.stringToValue((String)token)); + newjo.accumulate(attribute, + XML.stringToValue((String)token)); token = null; - } else { - newjo.accumulate(attribute, ""); } + else + newjo.accumulate(attribute, ""); } - if (arrayForm && newjo.length() > 0) { + if (arrayForm && newjo.length() > 0) newja.put(newjo); - } // Empty tag <.../> if (token == XML.SLASH) { - if (x.nextToken() != XML.GT) { + if (x.nextToken() != XML.GT) throw x.syntaxError("Misshaped tag"); - } - if (ja == null) { - if (arrayForm) { + if (ja == null) + if (arrayForm) return newja; - } else { + else return newjo; - } - } // Content, between <...> and - } else { - if (token != XML.GT) { + } + else { + if (token != XML.GT) throw x.syntaxError("Misshaped tag"); - } closeTag = (String)parse(x, arrayForm, newja); if (closeTag != null) { - if (!closeTag.equals(tagName)) { - throw x.syntaxError("Mismatched '" + tagName + - "' and '" + closeTag + "'"); - } + if (!closeTag.equals(tagName)) + throw x.syntaxError("Mismatched '" + tagName + + "' and '" + closeTag + "'"); tagName = null; - if (!arrayForm && newja.length() > 0) { + if (!arrayForm && newja.length() > 0) newjo.put("childNodes", newja); - } - if (ja == null) { - if (arrayForm) { + if (ja == null) + if (arrayForm) return newja; - } else { + else return newjo; - } - } } } } - } else { - if (ja != null) { - ja.put(token instanceof String - ? XML.stringToValue((String)token) - : token); - } } + else if (ja != null) + ja.put(token instanceof String + ? XML.stringToValue((String)token) : token); } } - /** * Convert a well-formed (but not necessarily valid) XML string into a - * JSONArray using the JsonML transform. Each XML tag is represented as - * a JSONArray in which the first element is the tag name. If the tag has + * JSONArray using the JsonML transform. Each XML tag is represented as a + * JSONArray in which the first element is the tag name. If the tag has * attributes, then the second element will be JSONObject containing the * name/value pairs. If the tag contains children, then strings and - * JSONArrays will represent the child tags. - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. + * JSONArrays will represent the child tags. Comments, prologs, DTDs, and + * <[ [ ]]> are ignored. + * * @param string The source string. * @return A JSONArray containing the structured data from the XML string. - * @throws JSONException + * @throws JSONException If something goes wrong */ - public static JSONArray toJSONArray(String string) throws JSONException { + public static JSONArray toJSONArray(final String string) + throws JSONException + { return toJSONArray(new XMLTokener(string)); } - /** * Convert a well-formed (but not necessarily valid) XML string into a - * JSONArray using the JsonML transform. Each XML tag is represented as - * a JSONArray in which the first element is the tag name. If the tag has + * JSONArray using the JsonML transform. Each XML tag is represented as a + * JSONArray in which the first element is the tag name. If the tag has * attributes, then the second element will be JSONObject containing the * name/value pairs. If the tag contains children, then strings and - * JSONArrays will represent the child content and tags. - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. + * JSONArrays will represent the child content and tags. Comments, prologs, + * DTDs, and <[ [ ]]> are ignored. + * * @param x An XMLTokener. * @return A JSONArray containing the structured data from the XML string. - * @throws JSONException + * @throws JSONException If something goes wrong */ - public static JSONArray toJSONArray(XMLTokener x) throws JSONException { + public static JSONArray toJSONArray(final XMLTokener x) + throws JSONException + { return (JSONArray)parse(x, true, null); } - /** * Convert a well-formed (but not necessarily valid) XML string into a - * JSONObject using the JsonML transform. Each XML tag is represented as - * a JSONObject with a "tagName" property. If the tag has attributes, then - * the attributes will be in the JSONObject as properties. If the tag - * contains children, the object will have a "childNodes" property which - * will be an array of strings and JsonML JSONObjects. - - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. + * JSONObject using the JsonML transform. Each XML tag is represented as a + * JSONObject with a "tagName" property. If the tag has attributes, then the + * attributes will be in the JSONObject as properties. If the tag contains + * children, the object will have a "childNodes" property which will be an + * array of strings and JsonML JSONObjects. Comments, prologs, DTDs, and + * <[ [ ]]> are ignored. + * * @param x An XMLTokener of the XML source text. * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException + * @throws JSONException If something goes wrong */ - public static JSONObject toJSONObject(XMLTokener x) throws JSONException { - return (JSONObject)parse(x, false, null); + public static JSONObject toJSONObject(final XMLTokener x) + throws JSONException + { + return (JSONObject)parse(x, false, null); } - /** * Convert a well-formed (but not necessarily valid) XML string into a - * JSONObject using the JsonML transform. Each XML tag is represented as - * a JSONObject with a "tagName" property. If the tag has attributes, then - * the attributes will be in the JSONObject as properties. If the tag - * contains children, the object will have a "childNodes" property which - * will be an array of strings and JsonML JSONObjects. - - * Comments, prologs, DTDs, and <[ [ ]]> are ignored. + * JSONObject using the JsonML transform. Each XML tag is represented as a + * JSONObject with a "tagName" property. If the tag has attributes, then the + * attributes will be in the JSONObject as properties. If the tag contains + * children, the object will have a "childNodes" property which will be an + * array of strings and JsonML JSONObjects. Comments, prologs, DTDs, and + * <[ [ ]]> are ignored. + * * @param string The XML source text. * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException + * @throws JSONException If something goes wrong */ - public static JSONObject toJSONObject(String string) throws JSONException { + public static JSONObject toJSONObject(final String string) + throws JSONException + { return toJSONObject(new XMLTokener(string)); } - /** * Reverse the JSONML transformation, making an XML text from a JSONArray. + * * @param ja A JSONArray. * @return An XML string. - * @throws JSONException + * @throws JSONException If something goes wrong */ - public static String toString(JSONArray ja) throws JSONException { - int i; - JSONObject jo; - String key; - Iterator keys; - int length; - Object object; - StringBuilder sb = new StringBuilder(); - String tagName; - String value; + public static String toString(final JSONArray ja) throws JSONException { + int i; + JSONObject jo; + String key; + Iterator keys; + int length; + Object object; + final StringBuilder sb = new StringBuilder(); + String tagName; + String value; // Emit = length) { sb.append('/'); sb.append('>'); - } else { + } + else { sb.append('>'); do { object = ja.get(i); i += 1; - if (object != null) { - if (object instanceof String) { + if (object != null) + if (object instanceof String) sb.append(XML.escape(object.toString())); - } else if (object instanceof JSONObject) { + else if (object instanceof JSONObject) sb.append(toString((JSONObject)object)); - } else if (object instanceof JSONArray) { + else if (object instanceof JSONArray) sb.append(toString((JSONArray)object)); - } else { + else sb.append(object.toString()); - } - } } while (i < length); sb.append('<'); sb.append('/'); @@ -391,27 +374,27 @@ public static String toString(JSONArray ja) throws JSONException { * The JSONObject must contain a "tagName" property. If it has children, * then it must have a "childNodes" property containing an array of objects. * The other properties are attributes with string values. + * * @param jo A JSONObject. * @return An XML string. - * @throws JSONException + * @throws JSONException If something goes wrong */ - public static String toString(JSONObject jo) throws JSONException { - StringBuilder sb = new StringBuilder(); - int i; - JSONArray ja; - String key; - Iterator keys; - int length; - Object object; - String tagName; - String value; + public static String toString(final JSONObject jo) throws JSONException { + final StringBuilder sb = new StringBuilder(); + int i; + JSONArray ja; + String key; + Iterator keys; + int length; + Object object; + String tagName; + String value; //Emit '); - } else { + } + else { sb.append('>'); length = ja.length(); for (i = 0; i < length; i += 1) { object = ja.get(i); - if (object != null) { - if (object instanceof String) { + if (object != null) + if (object instanceof String) sb.append(XML.escape(object.toString())); - } else if (object instanceof JSONObject) { + else if (object instanceof JSONObject) sb.append(toString((JSONObject)object)); - } else if (object instanceof JSONArray) { + else if (object instanceof JSONArray) sb.append(toString((JSONArray)object)); - } else { + else sb.append(object.toString()); - } - } } sb.append('<'); sb.append('/'); diff --git a/JSONObject.java b/JSONObject.java index e2e30dfaf..6b897ae14 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -23,53 +23,40 @@ of this software and associated documentation files (the "Software"), to deal OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.math.*; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Locale; -import java.util.Map; -import java.util.ResourceBundle; -import java.util.Set; +import java.io.*; +import java.lang.reflect.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.*; +import java.util.Map.Entry; /** * 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, + * 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. + * 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, + * 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"}. @@ -82,18 +69,18 @@ of this software and associated documentation files (the "Software"), to deal * before the closing brace. *
  • Strings may be quoted with ' (single * quote).
  • - *
  • Strings do not need to be quoted at all if they do not begin with a - * quote or single quote, and if they do not contain leading or trailing - * spaces, and if they do not contain any of these characters: - * { } [ ] / \ : , # and if they do not look like numbers and - * if they are not the reserved words true, false, - * or null.
  • + *
  • Strings do not need to be quoted at all if they do not begin with a quote + * or single quote, and if they do not contain leading or trailing spaces, and + * if they do not contain any of these characters: + * { } [ ] / \ : , # and if they do not look like numbers and if + * they are not the reserved words true, false, or + * null.
  • * * * @author JSON.org * @version 2015-12-09 */ -public class JSONObject extends HashMap { +public class JSONObject extends TreeMap { /** * JSONObject.NULL is equivalent to the value that JavaScript calls null, * whilst Java's null is equivalent to the value that JavaScript calls @@ -102,8 +89,8 @@ public class JSONObject extends HashMap { private static final class Null { /** - * There is only intended to be a single instance of the NULL object, - * so the clone method returns itself. + * There is only intended to be a single instance of the NULL object, so + * the clone method returns itself. * * @return NULL. */ @@ -115,13 +102,12 @@ protected final Object clone() { /** * A Null object is equal to the null value and to itself. * - * @param object - * An object to test for nullness. + * @param object An object to test for nullness. * @return true if the object parameter is the JSONObject.NULL object or * null. */ @Override - public boolean equals(Object object) { + public boolean equals(final Object object) { return object == null || object == this; } @@ -156,72 +142,63 @@ public JSONObject() { * strings is used to identify the keys that should be copied. Missing keys * are ignored. * - * @param jo - * A JSONObject. - * @param names - * An array of strings. + * @param jo A JSONObject. + * @param names An array of strings. */ - public JSONObject(JSONObject jo, String[] names) { + public JSONObject(final JSONObject jo, final String[] names) { this(); - for (int i = 0; i < names.length; i += 1) { + for (final String name : names) try { - putOnce(names[i], jo.opt(names[i])); - } catch (Exception ignore) { - } - } + putOnce(name, jo.opt(name)); + } catch (final Exception ignore) {} } /** * Construct a JSONObject from a JSONTokener. * - * @param x - * A JSONTokener object containing the source string. - * @throws JSONException - * If there is a syntax error in the source string or a - * duplicated key. + * @param x A JSONTokener object containing the source string. + * @throws JSONException If there is a syntax error in the source string or + * a duplicated key. */ - public JSONObject(JSONTokener x) throws JSONException { + public JSONObject(final JSONTokener x) throws JSONException { this(); char c; String key; - if (x.nextClean() != '{') { + if (x.nextClean() != '{') throw x.syntaxError("A JSONObject text must begin with '{'"); - } for (;;) { c = x.nextClean(); switch (c) { - case 0: - throw x.syntaxError("A JSONObject text must end with '}'"); - case '}': - return; - default: - x.back(); - key = x.nextValue().toString(); + case 0: + throw x.syntaxError("A JSONObject text must end with '}'"); + case '}': + return; + default: + x.back(); + key = x.nextValue().toString(); } // The key is followed by ':'. c = x.nextClean(); - if (c != ':') { + if (c != ':') throw x.syntaxError("Expected a ':' after a key"); - } putOnce(key, x.nextValue()); // Pairs are separated by ','. switch (x.nextClean()) { - case ';': - case ',': - if (x.nextClean() == '}') { + case ';': + case ',': + if (x.nextClean() == '}') + return; + x.back(); + break; + case '}': return; - } - x.back(); - break; - case '}': - return; - default: - throw x.syntaxError("Expected a ',' or '}'"); + default: + throw x.syntaxError("Expected a ',' or '}'"); } } } @@ -229,20 +206,17 @@ public JSONObject(JSONTokener x) throws JSONException { /** * Construct a JSONObject from a Map. * - * @param map - * A map object that can be used to initialize the contents of + * @param map A map object that can be used to initialize the contents of * the JSONObject. */ - public JSONObject(Map map) { + public JSONObject(final Map map) { this(); - if (map != null) { + if (map != null) for (final Entry e : map.entrySet()) { final Object value = e.getValue(); - if (value != null) { + if (value != null) super.put(String.valueOf(e.getKey()), wrap(value)); - } } - } } /** @@ -251,22 +225,17 @@ public JSONObject(Map map) { * parameters and a name starting with "get" or * "is" followed by an uppercase letter, the method is invoked, * and a key and the value returned from the getter method are put into the - * new JSONObject. - * - * The key is formed by removing the "get" or "is" - * prefix. If the second remaining character is not upper case, then the - * first character is converted to lower case. - * - * For example, if an object has a method named "getName", and - * if the result of calling object.getName() is - * "Larry Fine", then the JSONObject will contain - * "name": "Larry Fine". - * - * @param bean - * An object that has getter methods that should be used to make + * new JSONObject. The key is formed by removing the "get" or + * "is" prefix. If the second remaining character is not upper + * case, then the first character is converted to lower case. For example, + * if an object has a method named "getName", and if the result + * of calling object.getName() is "Larry Fine", + * then the JSONObject will contain "name": "Larry Fine". + * + * @param bean An object that has getter methods that should be used to make * a JSONObject. */ - public JSONObject(Object bean) { + public JSONObject(final Object bean) { this(); populateMap(bean); } @@ -278,72 +247,64 @@ public JSONObject(Object bean) { * those keys in the object. If a key is not found or not visible, then it * will not be copied into the new JSONObject. * - * @param object - * An object that has fields that should be used to make a + * @param object An object that has fields that should be used to make a * JSONObject. - * @param names - * An array of strings, the names of the fields to be obtained + * @param names An array of strings, the names of the fields to be obtained * from the object. */ - public JSONObject(Object object, String names[]) { + public JSONObject(final Object object, final String names[]) { this(); - Class c = object.getClass(); - for (int i = 0; i < names.length; i += 1) { - String name = names[i]; + final Class c = object.getClass(); + for (final String name : names) try { putOpt(name, c.getField(name).get(object)); - } catch (Exception ignore) { - } - } + } catch (final Exception ignore) {} } /** * Construct a JSONObject from a source JSON text string. This is the most * commonly used JSONObject constructor. * - * @param source - * A string beginning with { (left - * brace) and ending with } - *  (right brace). - * @exception JSONException - * If there is a syntax error in the source string or a - * duplicated key. + * @param source A string beginning with { (left + * brace) and ending with }   + * (right brace). + * @exception JSONException If there is a syntax error in the source string + * or a duplicated key. */ - public JSONObject(String source) throws JSONException { + public JSONObject(final String source) throws JSONException { this(new JSONTokener(source)); } /** * Construct a JSONObject from a ResourceBundle. * - * @param baseName - * The ResourceBundle base name. - * @param locale - * The Locale to load the ResourceBundle for. - * @throws JSONException - * If any JSONExceptions are detected. + * @param baseName The ResourceBundle base name. + * @param locale The Locale to load the ResourceBundle for. + * @throws JSONException If any JSONExceptions are detected. */ - public JSONObject(String baseName, Locale locale) throws JSONException { + public JSONObject(final String baseName, final Locale locale) + throws JSONException + { this(); - ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, - Thread.currentThread().getContextClassLoader()); + final ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, + Thread.currentThread().getContextClassLoader()); // Iterate through the keys in the bundle. - Enumeration keys = bundle.getKeys(); + final Enumeration keys = bundle.getKeys(); while (keys.hasMoreElements()) { - Object key = keys.nextElement(); + final Object key = keys.nextElement(); if (key != null) { // Go through the path, ensuring that there is a nested JSONObject for each // segment except the last. Add the value using the last segment's name into // the deepest nested JSONObject. - String[] path = ((String) key).split("\\."); - int last = path.length - 1; + final String[] path = ((String)key).split("\\."); + final int last = path.length - 1; JSONObject target = this; for (int i = 0; i < last; i += 1) { - String segment = path[i]; + final String segment = path[i]; JSONObject nextTarget = target.optJSONObject(segment); if (nextTarget == null) { nextTarget = new JSONObject(); @@ -351,7 +312,7 @@ public JSONObject(String baseName, Locale locale) throws JSONException { } target = nextTarget; } - target.put(path[last], bundle.getString((String) key)); + target.put(path[last], bundle.getString((String)key)); } } } @@ -361,30 +322,29 @@ public JSONObject(String baseName, Locale locale) throws JSONException { * that if there is already an object stored under the key then a JSONArray * is stored under the key to hold all of the accumulated values. If there * is already a JSONArray, then the new value is appended to it. In - * contrast, the put method replaces the previous value. + * contrast, the put method replaces the previous value. If only one value + * is accumulated that is not a JSONArray, then the result will be the same + * as using put. But if multiple values are accumulated, then the result + * will be like append. * - * If only one value is accumulated that is not a JSONArray, then the result - * will be the same as using put. But if multiple values are accumulated, - * then the result will be like append. - * - * @param key - * A key string. - * @param value - * An object to be accumulated under the key. + * @param key A key string. + * @param value An object to be accumulated under the key. * @return this. - * @throws JSONException - * If the value is an invalid number or if the key is null. + * @throws JSONException If the value is an invalid number or if the key is + * null. */ - public JSONObject accumulate(String key, Object value) throws JSONException { + public JSONObject accumulate(final String key, final Object value) + throws JSONException + { testValidity(value); - Object object = opt(key); - if (object == null) { - put(key, value instanceof JSONArray ? new JSONArray().put(value) : value); - } else if (object instanceof JSONArray) { - ((JSONArray) object).put(value); - } else { + final Object object = opt(key); + if (object == null) + put(key, value instanceof JSONArray ? new JSONArray().put(value) + : value); + else if (object instanceof JSONArray) + ((JSONArray)object).put(value); + else this.put(key, new JSONArray().put(object).put(value)); - } return this; } @@ -394,26 +354,24 @@ public JSONObject accumulate(String key, Object value) throws JSONException { * JSONArray containing the value parameter. If the key was already * associated with a JSONArray, then the value parameter is appended to it. * - * @param key - * A key string. - * @param value - * An object to be accumulated under the key. + * @param key A key string. + * @param value An object to be accumulated under the key. * @return this. - * @throws JSONException - * If the key is null or if the current value associated with - * the key is not a JSONArray. + * @throws JSONException If the key is null or if the current value + * associated with the key is not a JSONArray. */ - public JSONObject append(String key, Object value) throws JSONException { + public JSONObject append(final String key, final Object value) + throws JSONException + { testValidity(value); - Object object = opt(key); - if (object == null) { + final Object object = opt(key); + if (object == null) this.put(key, new JSONArray().put(value)); - } else if (object instanceof JSONArray) { - this.put(key, ((JSONArray) object).put(value)); - } else { - throw new JSONException("JSONObject[" + key - + "] is not a JSONArray."); - } + else if (object instanceof JSONArray) + this.put(key, ((JSONArray)object).put(value)); + else + throw new JSONException( + "JSONObject[" + key + "] is not a JSONArray."); return this; } @@ -421,26 +379,23 @@ public JSONObject append(String key, Object value) throws JSONException { * Produce a string from a double. The string "null" will be returned if the * number is not finite. * - * @param d - * A double. + * @param d A double. * @return A String. */ - public static String doubleToString(double d) { - if (Double.isInfinite(d) || Double.isNaN(d)) { + public static String doubleToString(final double d) { + if (Double.isInfinite(d) || Double.isNaN(d)) return "null"; - } // Shave off trailing zeros and decimal point, if possible. String string = Double.toString(d); if (string.indexOf('.') > 0 && string.indexOf('e') < 0 - && string.indexOf('E') < 0) { - while (string.endsWith("0")) { + && string.indexOf('E') < 0) + { + while (string.endsWith("0")) string = string.substring(0, string.length() - 1); - } - if (string.endsWith(".")) { + if (string.endsWith(".")) string = string.substring(0, string.length() - 1); - } } return string; } @@ -448,224 +403,201 @@ public static String doubleToString(double d) { /** * Get the value object associated with a key. * - * @param key - * A key string. + * @param key A key string. * @return The object associated with the key. - * @throws JSONException - * if the key is not found. + * @throws JSONException if the key is not found. */ - public Object get(String key) throws JSONException { - if (key == null) { + public Object get(final String key) throws JSONException { + if (key == null) throw new JSONException("Null key."); - } - Object object = opt(key); - if (object == null) { - throw new JSONException("JSONObject[" + quote(key) + "] not found."); - } + final Object object = opt(key); + if (object == null) + throw new JSONException( + "JSONObject[" + quote(key) + "] not found."); return object; } /** - * Get the enum value associated with a key. - * - * @param clazz - * The type of enum to retrieve. - * @param key - * A key string. - * @return The enum value associated with the key - * @throws JSONException - * if the key is not found or if the value cannot be converted - * to an enum. - */ - public > E getEnum(Class clazz, String key) throws JSONException { - E val = optEnum(clazz, key); - if(val==null) { + * Get the enum value associated with a key. + * + * @param The enum type + * @param clazz The type of enum to retrieve. + * @param key A key string. + * @return The enum value associated with the key + * @throws JSONException if the key is not found or if the value cannot be + * converted to an enum. + */ + public > E getEnum(final Class clazz, final String key) + throws JSONException + { + final E val = optEnum(clazz, key); + if (val == null) // JSONException should really take a throwable argument. // If it did, I would re-implement this with the Enum.valueOf // method and place any thrown exception in the JSONException - throw new JSONException("JSONObject[" + quote(key) - + "] is not an enum of type " + quote(clazz.getSimpleName()) - + "."); - } + throw new JSONException( + "JSONObject[" + quote(key) + "] is not an enum of type " + + quote(clazz.getSimpleName()) + "."); return val; } /** * Get the boolean value associated with a key. * - * @param key - * A key string. + * @param key A key string. * @return The truth. - * @throws JSONException - * if the value is not a Boolean or the String "true" or - * "false". - */ - public boolean getBoolean(String key) throws JSONException { - Object object = this.get(key); - if (object.equals(Boolean.FALSE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("false"))) { + * @throws JSONException if the value is not a Boolean or the String "true" + * or "false". + */ + public boolean getBoolean(final String key) throws JSONException { + final Object object = this.get(key); + if (object.equals(Boolean.FALSE) || object instanceof String + && ((String)object).equalsIgnoreCase("false")) return false; - } else if (object.equals(Boolean.TRUE) - || (object instanceof String && ((String) object) - .equalsIgnoreCase("true"))) { + else if (object.equals(Boolean.TRUE) || object instanceof String + && ((String)object).equalsIgnoreCase("true")) return true; - } - throw new JSONException("JSONObject[" + quote(key) - + "] is not a Boolean."); + throw new JSONException( + "JSONObject[" + quote(key) + "] is not a Boolean."); } /** * Get the BigInteger value associated with a key. * - * @param key - * A key string. + * @param key A key string. * @return The numeric value. - * @throws JSONException - * if the key is not found or if the value cannot - * be converted to BigInteger. + * @throws JSONException if the key is not found or if the value cannot be + * converted to BigInteger. */ - public BigInteger getBigInteger(String key) throws JSONException { - Object object = this.get(key); + public BigInteger getBigInteger(final String key) throws JSONException { + final Object object = this.get(key); try { return new BigInteger(object.toString()); - } catch (Exception e) { + } catch (final Exception e) { throw new JSONException("JSONObject[" + quote(key) - + "] could not be converted to BigInteger."); + + "] could not be converted to BigInteger."); } } /** * Get the BigDecimal value associated with a key. * - * @param key - * A key string. + * @param key A key string. * @return The numeric value. - * @throws JSONException - * if the key is not found or if the value - * cannot be converted to BigDecimal. + * @throws JSONException if the key is not found or if the value cannot be + * converted to BigDecimal. */ - public BigDecimal getBigDecimal(String key) throws JSONException { - Object object = this.get(key); + public BigDecimal getBigDecimal(final String key) throws JSONException { + final Object object = this.get(key); try { return new BigDecimal(object.toString()); - } catch (Exception e) { + } catch (final Exception e) { throw new JSONException("JSONObject[" + quote(key) - + "] could not be converted to BigDecimal."); + + "] could not be converted to BigDecimal."); } } /** * Get the double value associated with a key. * - * @param key - * A key string. + * @param key A key string. * @return The numeric value. - * @throws JSONException - * if the key is not found or if the value is not a Number - * object and cannot be converted to a number. + * @throws JSONException if the key is not found or if the value is not a + * Number object and cannot be converted to a number. */ - public double getDouble(String key) throws JSONException { - Object object = this.get(key); + public double getDouble(final String key) throws JSONException { + final Object object = this.get(key); try { - return object instanceof Number ? ((Number) object).doubleValue() - : Double.parseDouble((String) object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) - + "] is not a number."); + return object instanceof Number ? ((Number)object).doubleValue() + : Double.parseDouble((String)object); + } catch (final Exception e) { + throw new JSONException( + "JSONObject[" + quote(key) + "] is not a number."); } } /** * Get the int value associated with a key. * - * @param key - * A key string. + * @param key A key string. * @return The integer value. - * @throws JSONException - * if the key is not found or if the value cannot be converted - * to an integer. + * @throws JSONException if the key is not found or if the value cannot be + * converted to an integer. */ - public int getInt(String key) throws JSONException { - Object object = this.get(key); + public int getInt(final String key) throws JSONException { + final Object object = this.get(key); try { - return object instanceof Number ? ((Number) object).intValue() - : Integer.parseInt((String) object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) - + "] is not an int."); + return object instanceof Number ? ((Number)object).intValue() + : Integer.parseInt((String)object); + } catch (final Exception e) { + throw new JSONException( + "JSONObject[" + quote(key) + "] is not an int."); } } /** * Get the JSONArray value associated with a key. * - * @param key - * A key string. + * @param key A key string. * @return A JSONArray which is the value. - * @throws JSONException - * if the key is not found or if the value is not a JSONArray. + * @throws JSONException if the key is not found or if the value is not a + * JSONArray. */ - public JSONArray getJSONArray(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof JSONArray) { - return (JSONArray) object; - } - throw new JSONException("JSONObject[" + quote(key) - + "] is not a JSONArray."); + public JSONArray getJSONArray(final String key) throws JSONException { + final Object object = this.get(key); + if (object instanceof JSONArray) + return (JSONArray)object; + throw new JSONException( + "JSONObject[" + quote(key) + "] is not a JSONArray."); } /** * Get the JSONObject value associated with a key. * - * @param key - * A key string. + * @param key A key string. * @return A JSONObject which is the value. - * @throws JSONException - * if the key is not found or if the value is not a JSONObject. + * @throws JSONException if the key is not found or if the value is not a + * JSONObject. */ - public JSONObject getJSONObject(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof JSONObject) { - return (JSONObject) object; - } - throw new JSONException("JSONObject[" + quote(key) - + "] is not a JSONObject."); + public JSONObject getJSONObject(final String key) throws JSONException { + final Object object = this.get(key); + if (object instanceof JSONObject) + return (JSONObject)object; + throw new JSONException( + "JSONObject[" + quote(key) + "] is not a JSONObject."); } /** * Get the long value associated with a key. * - * @param key - * A key string. + * @param key A key string. * @return The long value. - * @throws JSONException - * if the key is not found or if the value cannot be converted - * to a long. + * @throws JSONException if the key is not found or if the value cannot be + * converted to a long. */ - public long getLong(String key) throws JSONException { - Object object = this.get(key); + public long getLong(final String key) throws JSONException { + final Object object = this.get(key); try { - return object instanceof Number ? ((Number) object).longValue() - : Long.parseLong((String) object); - } catch (Exception e) { - throw new JSONException("JSONObject[" + quote(key) - + "] is not a long."); + return object instanceof Number ? ((Number)object).longValue() + : Long.parseLong((String)object); + } catch (final Exception e) { + throw new JSONException( + "JSONObject[" + quote(key) + "] is not a long."); } } /** * Get an array of field names from a JSONObject. * + * @param jo The object to get names from * @return An array of field names, or null if there are no names. */ - public static String[] getNames(JSONObject jo) { - int length = jo.length(); - if (length == 0) { + public static String[] getNames(final JSONObject jo) { + final int length = jo.length(); + if (length == 0) return null; - } - Iterator iterator = jo.keys(); - String[] names = new String[length]; + final Iterator iterator = jo.keys(); + final String[] names = new String[length]; int i = 0; while (iterator.hasNext()) { names[i] = iterator.next(); @@ -677,50 +609,44 @@ public static String[] getNames(JSONObject jo) { /** * Get an array of field names from an Object. * + * @param object The object * @return An array of field names, or null if there are no names. */ - public static String[] getNames(Object object) { - if (object == null) { + public static String[] getNames(final Object object) { + if (object == null) return null; - } - Class klass = object.getClass(); - Field[] fields = klass.getFields(); - int length = fields.length; - if (length == 0) { + final Class klass = object.getClass(); + final Field[] fields = klass.getFields(); + final int length = fields.length; + if (length == 0) return null; - } - String[] names = new String[length]; - for (int i = 0; i < length; i += 1) { + final String[] names = new String[length]; + for (int i = 0; i < length; i += 1) names[i] = fields[i].getName(); - } return names; } /** * Get the string associated with a key. * - * @param key - * A key string. + * @param key A key string. * @return A string which is the value. - * @throws JSONException - * if there is no string value for the key. + * @throws JSONException if there is no string value for the key. */ - public String getString(String key) throws JSONException { - Object object = this.get(key); - if (object instanceof String) { - return (String) object; - } + public String getString(final String key) throws JSONException { + final Object object = this.get(key); + if (object instanceof String) + return (String)object; throw new JSONException("JSONObject[" + quote(key) + "] not a string."); } /** * Determine if the JSONObject contains a specific key. * - * @param key - * A key string. + * @param key A key string. * @return true if the key exists in the JSONObject. */ - public boolean has(String key) { + public boolean has(final String key) { return containsKey(key); } @@ -729,32 +655,30 @@ public boolean has(String key) { * create one with a value of 1. If there is such a property, and if it is * an Integer, Long, Double, or Float, then add one to it. * - * @param key - * A key string. + * @param key A key string. * @return this. - * @throws JSONException - * If there is already a property with this name that is not an - * Integer, Long, Double, or Float. + * @throws JSONException If there is already a property with this name that + * is not an Integer, Long, Double, or Float. */ - public JSONObject increment(String key) throws JSONException { - Object value = opt(key); - if (value == null) { + public JSONObject increment(final String key) throws JSONException { + final Object value = opt(key); + if (value == null) this.put(key, 1); - } else if (value instanceof BigInteger) { + else if (value instanceof BigInteger) this.put(key, ((BigInteger)value).add(BigInteger.ONE)); - } else if (value instanceof BigDecimal) { + else if (value instanceof BigDecimal) this.put(key, ((BigDecimal)value).add(BigDecimal.ONE)); - } else if (value instanceof Integer) { - this.put(key, (Integer) value + 1); - } else if (value instanceof Long) { - this.put(key, (Long) value + 1); - } else if (value instanceof Double) { - this.put(key, (Double) value + 1); - } else if (value instanceof Float) { - this.put(key, (Float) value + 1); - } else { - throw new JSONException("Unable to increment [" + quote(key) + "]."); - } + else if (value instanceof Integer) + this.put(key, (Integer)value + 1); + else if (value instanceof Long) + this.put(key, (Long)value + 1); + else if (value instanceof Double) + this.put(key, (Double)value + 1); + else if (value instanceof Float) + this.put(key, (Float)value + 1); + else + throw new JSONException( + "Unable to increment [" + quote(key) + "]."); return this; } @@ -762,12 +686,11 @@ public JSONObject increment(String key) throws JSONException { * Determine if the value associated with the key is null or if there is no * value. * - * @param key - * A key string. + * @param key A key string. * @return true if there is no value associated with the key or if the value * is the JSONObject.NULL object. */ - public boolean isNull(String key) { + public boolean isNull(final String key) { return JSONObject.NULL.equals(opt(key)); } @@ -797,40 +720,37 @@ public int length() { * is empty. */ public JSONArray names() { - JSONArray ja = new JSONArray(); - Iterator keys = keys(); - while (keys.hasNext()) { + final JSONArray ja = new JSONArray(); + final Iterator keys = keys(); + while (keys.hasNext()) ja.put(keys.next()); - } return ja.length() == 0 ? null : ja; } /** * Produce a string from a Number. * - * @param number - * A Number + * @param number A Number * @return A String. - * @throws JSONException - * If n is a non-finite number. + * @throws JSONException If n is a non-finite number. */ - public static String numberToString(Number number) throws JSONException { - if (number == null) { + public static String numberToString(final Number number) + throws JSONException + { + if (number == null) throw new JSONException("Null pointer"); - } testValidity(number); // Shave off trailing zeros and decimal point, if possible. String string = number.toString(); if (string.indexOf('.') > 0 && string.indexOf('e') < 0 - && string.indexOf('E') < 0) { - while (string.endsWith("0")) { + && string.indexOf('E') < 0) + { + while (string.endsWith("0")) string = string.substring(0, string.length() - 1); - } - if (string.endsWith(".")) { + if (string.endsWith(".")) string = string.substring(0, string.length() - 1); - } } return string; } @@ -838,49 +758,48 @@ public static String numberToString(Number number) throws JSONException { /** * Get an optional value associated with a key. * - * @param key - * A key string. + * @param key A key string. * @return An object which is the value, or null if there is no value. */ - public Object opt(String key) { + public Object opt(final String key) { return key == null ? null : super.get(key); } /** * Get the enum value associated with a key. - * - * @param clazz - * The type of enum to retrieve. - * @param key - * A key string. + * + * @param The enum type + * @param clazz The type of enum to retrieve. + * @param key A key string. * @return The enum value associated with the key or null if not found */ - public > E optEnum(Class clazz, String key) { + public > E optEnum(final Class clazz, + final String key) + { return this.optEnum(clazz, key, null); } /** * Get the enum value associated with a key. - * - * @param clazz - * The type of enum to retrieve. - * @param key - * A key string. - * @param defaultValue - * The default in case the value is not found - * @return The enum value associated with the key or defaultValue - * if the value is not found or cannot be assigned to clazz - */ - public > E optEnum(Class clazz, String key, E defaultValue) { + * + * @param The enum type + * @param clazz The type of enum to retrieve. + * @param key A key string. + * @param defaultValue The default in case the value is not found + * @return The enum value associated with the key or defaultValue if the + * value is not found or cannot be assigned to clazz + */ + public > E optEnum(final Class clazz, final String key, + final E defaultValue) + { try { - Object val = opt(key); - if (NULL.equals(val)) { + final Object val = opt(key); + if (NULL.equals(val)) return defaultValue; - } if (clazz.isAssignableFrom(val.getClass())) { // we just checked it! @SuppressWarnings("unchecked") - E myE = (E) val; + final E myE = (E)val; return myE; } return Enum.valueOf(clazz, val.toString()); @@ -893,11 +812,10 @@ public > E optEnum(Class clazz, String key, E defaultValue) * Get an optional boolean associated with a key. It returns false if there * is no such key, or if the value is not Boolean.TRUE or the String "true". * - * @param key - * A key string. + * @param key A key string. * @return The truth. */ - public boolean optBoolean(String key) { + public boolean optBoolean(final String key) { return this.optBoolean(key, false); } @@ -906,16 +824,14 @@ public boolean optBoolean(String key) { * defaultValue if there is no such key, or if it is not a Boolean or the * String "true" or "false" (case insensitive). * - * @param key - * A key string. - * @param defaultValue - * The default. + * @param key A key string. + * @param defaultValue The default. * @return The truth. */ - public boolean optBoolean(String key, boolean defaultValue) { + public boolean optBoolean(final String key, final boolean defaultValue) { try { return getBoolean(key); - } catch (Exception e) { + } catch (final Exception e) { return defaultValue; } } @@ -925,11 +841,10 @@ public boolean optBoolean(String key, boolean defaultValue) { * key or if its value is not a number. If the value is a string, an attempt * will be made to evaluate it as a number. * - * @param key - * A string which is the key. + * @param key A string which is the key. * @return An object which is the value. */ - public double optDouble(String key) { + public double optDouble(final String key) { return this.optDouble(key, Double.NaN); } @@ -938,16 +853,16 @@ public double optDouble(String key) { * there is no such key or if its value is not a number. If the value is a * string, an attempt will be made to evaluate it as a number. * - * @param key - * A key string. - * @param defaultValue - * The default. + * @param key A key string. + * @param defaultValue The default. * @return An object which is the value. */ - public BigInteger optBigInteger(String key, BigInteger defaultValue) { + public BigInteger optBigInteger(final String key, + final BigInteger defaultValue) + { try { return getBigInteger(key); - } catch (Exception e) { + } catch (final Exception e) { return defaultValue; } } @@ -957,16 +872,16 @@ public BigInteger optBigInteger(String key, BigInteger defaultValue) { * there is no such key or if its value is not a number. If the value is a * string, an attempt will be made to evaluate it as a number. * - * @param key - * A key string. - * @param defaultValue - * The default. + * @param key A key string. + * @param defaultValue The default. * @return An object which is the value. */ - public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) { + public BigDecimal optBigDecimal(final String key, + final BigDecimal defaultValue) + { try { return getBigDecimal(key); - } catch (Exception e) { + } catch (final Exception e) { return defaultValue; } } @@ -976,16 +891,14 @@ public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) { * there is no such key or if its value is not a number. If the value is a * string, an attempt will be made to evaluate it as a number. * - * @param key - * A key string. - * @param defaultValue - * The default. + * @param key A key string. + * @param defaultValue The default. * @return An object which is the value. */ - public double optDouble(String key, double defaultValue) { + public double optDouble(final String key, final double defaultValue) { try { return getDouble(key); - } catch (Exception e) { + } catch (final Exception e) { return defaultValue; } } @@ -995,11 +908,10 @@ public double optDouble(String key, double defaultValue) { * such key or if the value is not a number. If the value is a string, an * attempt will be made to evaluate it as a number. * - * @param key - * A key string. + * @param key A key string. * @return An object which is the value. */ - public int optInt(String key) { + public int optInt(final String key) { return this.optInt(key, 0); } @@ -1008,16 +920,14 @@ public int optInt(String key) { * is no such key or if the value is not a number. If the value is a string, * an attempt will be made to evaluate it as a number. * - * @param key - * A key string. - * @param defaultValue - * The default. + * @param key A key string. + * @param defaultValue The default. * @return An object which is the value. */ - public int optInt(String key, int defaultValue) { + public int optInt(final String key, final int defaultValue) { try { return getInt(key); - } catch (Exception e) { + } catch (final Exception e) { return defaultValue; } } @@ -1026,26 +936,24 @@ public int optInt(String key, int defaultValue) { * Get an optional JSONArray associated with a key. It returns null if there * is no such key, or if its value is not a JSONArray. * - * @param key - * A key string. + * @param key A key string. * @return A JSONArray which is the value. */ - public JSONArray optJSONArray(String key) { - Object o = opt(key); - return o instanceof JSONArray ? (JSONArray) o : null; + public JSONArray optJSONArray(final String key) { + final Object o = opt(key); + return o instanceof JSONArray ? (JSONArray)o : null; } /** * Get an optional JSONObject associated with a key. It returns null if * there is no such key, or if its value is not a JSONObject. * - * @param key - * A key string. + * @param key A key string. * @return A JSONObject which is the value. */ - public JSONObject optJSONObject(String key) { - Object object = opt(key); - return object instanceof JSONObject ? (JSONObject) object : null; + public JSONObject optJSONObject(final String key) { + final Object object = opt(key); + return object instanceof JSONObject ? (JSONObject)object : null; } /** @@ -1053,11 +961,10 @@ public JSONObject optJSONObject(String key) { * such key or if the value is not a number. If the value is a string, an * attempt will be made to evaluate it as a number. * - * @param key - * A key string. + * @param key A key string. * @return An object which is the value. */ - public long optLong(String key) { + public long optLong(final String key) { return this.optLong(key, 0); } @@ -1066,16 +973,14 @@ public long optLong(String key) { * is no such key or if the value is not a number. If the value is a string, * an attempt will be made to evaluate it as a number. * - * @param key - * A key string. - * @param defaultValue - * The default. + * @param key A key string. + * @param defaultValue The default. * @return An object which is the value. */ - public long optLong(String key, long defaultValue) { + public long optLong(final String key, final long defaultValue) { try { return getLong(key); - } catch (Exception e) { + } catch (final Exception e) { return defaultValue; } } @@ -1085,11 +990,10 @@ public long optLong(String key, long defaultValue) { * if there is no such key. If the value is not a string and is not null, * then it is converted to a string. * - * @param key - * A key string. + * @param key A key string. * @return A string which is the value. */ - public String optString(String key) { + public String optString(final String key) { return this.optString(key, ""); } @@ -1097,75 +1001,67 @@ public String optString(String key) { * Get an optional string associated with a key. It returns the defaultValue * if there is no such key. * - * @param key - * A key string. - * @param defaultValue - * The default. + * @param key A key string. + * @param defaultValue The default. * @return A string which is the value. */ - public String optString(String key, String defaultValue) { - Object object = opt(key); + public String optString(final String key, final String defaultValue) { + final Object object = opt(key); return NULL.equals(object) ? defaultValue : object.toString(); } - private void populateMap(Object bean) { - Class klass = bean.getClass(); + private void populateMap(final Object bean) { + final Class klass = bean.getClass(); // If klass is a System class then set includeSuperClass to false. - boolean includeSuperClass = klass.getClassLoader() != null; + final boolean includeSuperClass = klass.getClassLoader() != null; - Method[] methods = includeSuperClass ? klass.getMethods() : klass - .getDeclaredMethods(); - for (int i = 0; i < methods.length; i += 1) { + final Method[] methods = includeSuperClass ? klass.getMethods() + : klass.getDeclaredMethods(); + for (final Method method : methods) try { - Method method = methods[i]; if (Modifier.isPublic(method.getModifiers())) { - String name = method.getName(); + final String name = method.getName(); String key = ""; if (name.startsWith("get")) { if ("getClass".equals(name) - || "getDeclaringClass".equals(name)) { + || "getDeclaringClass".equals(name)) key = ""; - } else { + else key = name.substring(3); - } - } else if (name.startsWith("is")) { - key = name.substring(2); } - if (key.length() > 0 - && Character.isUpperCase(key.charAt(0)) - && method.getParameterTypes().length == 0) { - if (key.length() == 1) { + else if (name.startsWith("is")) + key = name.substring(2); + if (key.length() > 0 && Character.isUpperCase(key.charAt(0)) + && method.getParameterTypes().length == 0) + { + if (key.length() == 1) key = key.toLowerCase(); - } else if (!Character.isUpperCase(key.charAt(1))) { + else if (!Character.isUpperCase(key.charAt(1))) key = key.substring(0, 1).toLowerCase() - + key.substring(1); - } + + key.substring(1); - Object result = method.invoke(bean, (Object[]) null); - if (result != null) { + final Object result = method.invoke(bean, + (Object[])null); + if (result != null) super.put(key, wrap(result)); - } } } - } catch (Exception ignore) { - } - } + } catch (final Exception ignore) {} } /** * Put a key/boolean pair in the JSONObject. * - * @param key - * A key string. - * @param value - * A boolean which is the value. + * @param key A key string. + * @param value A boolean which is the value. * @return this. - * @throws JSONException - * If the key is null. + * @throws JSONException If the key is null. */ - public JSONObject put(String key, boolean value) throws JSONException { + public JSONObject put(final String key, final boolean value) + throws JSONException + { this.put(key, value ? Boolean.TRUE : Boolean.FALSE); return this; } @@ -1174,29 +1070,29 @@ public JSONObject put(String key, boolean value) throws JSONException { * Put a key/value pair in the JSONObject, where the value will be a * JSONArray which is produced from a Collection. * - * @param key - * A key string. - * @param value - * A Collection value. + * @param key A key string. + * @param value A Collection value. * @return this. - * @throws JSONException + * @throws JSONException If the key is null or the value is invalid */ - public JSONObject put(String key, Collection value) throws JSONException { - return put(key, (Object) (value instanceof JSONArray ? value : new JSONArray(value))); + public JSONObject put(final String key, final Collection value) + throws JSONException + { + return put(key, (Object)(value instanceof JSONArray ? value + : new JSONArray(value))); } /** * Put a key/double pair in the JSONObject. * - * @param key - * A key string. - * @param value - * A double which is the value. + * @param key A key string. + * @param value A double which is the value. * @return this. - * @throws JSONException - * If the key is null or if the number is invalid. + * @throws JSONException If the key is null or if the number is invalid. */ - public JSONObject put(String key, double value) throws JSONException { + public JSONObject put(final String key, final double value) + throws JSONException + { this.put(key, new Double(value)); return this; } @@ -1204,15 +1100,14 @@ public JSONObject put(String key, double value) throws JSONException { /** * Put a key/int pair in the JSONObject. * - * @param key - * A key string. - * @param value - * An int which is the value. + * @param key A key string. + * @param value An int which is the value. * @return this. - * @throws JSONException - * If the key is null. + * @throws JSONException If the key is null. */ - public JSONObject put(String key, int value) throws JSONException { + public JSONObject put(final String key, final int value) + throws JSONException + { this.put(key, new Integer(value)); return this; } @@ -1220,15 +1115,14 @@ public JSONObject put(String key, int value) throws JSONException { /** * Put a key/long pair in the JSONObject. * - * @param key - * A key string. - * @param value - * A long which is the value. + * @param key A key string. + * @param value A long which is the value. * @return this. - * @throws JSONException - * If the key is null. + * @throws JSONException If the key is null. */ - public JSONObject put(String key, long value) throws JSONException { + public JSONObject put(final String key, final long value) + throws JSONException + { this.put(key, new Long(value)); return this; } @@ -1237,42 +1131,42 @@ public JSONObject put(String key, long value) throws JSONException { * Put a key/value pair in the JSONObject, where the value will be a * JSONObject which is produced from a Map. * - * @param key - * A key string. - * @param value - * A Map value. + * @param key A key string. + * @param value A Map value. * @return this. - * @throws JSONException + * @throws JSONException If the key is null or the value is invalid */ - public JSONObject put(String key, Map value) throws JSONException { - return put(key, (Object) (value instanceof JSONObject ? value : new JSONObject(value))); + public JSONObject put(final String key, final Map value) + throws JSONException + { + return put(key, (Object)(value instanceof JSONObject ? value + : new JSONObject(value))); } /** * Put a key/value pair in the JSONObject. If the value is null, then the * key will be removed from the JSONObject if it is present. * - * @param key - * A key string. - * @param value - * An object which is the value. It should be of one of these + * @param key A key string. + * @param value An object which is the value. It should be of one of these * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, * String, or the JSONObject.NULL object. * @return this. - * @throws JSONException - * If the value is non-finite number or if the key is null. + * @throws JSONException If the value is non-finite number or if the key is + * null. */ @Override - public JSONObject put(String key, Object value) throws JSONException { - if (key == null) { + public JSONObject put(final String key, final Object value) + throws JSONException + { + if (key == null) throw new NullPointerException("Null key."); - } if (value != null) { testValidity(value); super.put(key, value); - } else { - this.remove(key); } + else + this.remove(key); return this; } @@ -1284,14 +1178,14 @@ public JSONObject put(String key, Object value) throws JSONException { * @param key string * @param value object * @return this. - * @throws JSONException - * if the key is a duplicate + * @throws JSONException if the key is a duplicate */ - public JSONObject putOnce(String key, Object value) throws JSONException { + public JSONObject putOnce(final String key, final Object value) + throws JSONException + { if (key != null && value != null) { - if (opt(key) != null) { + if (opt(key) != null) throw new JSONException("Duplicate key \"" + key + "\""); - } this.put(key, value); } return this; @@ -1301,20 +1195,18 @@ public JSONObject putOnce(String key, Object value) throws JSONException { * Put a key/value pair in the JSONObject, but only if the key and the value * are both non-null. * - * @param key - * A key string. - * @param value - * An object which is the value. It should be of one of these + * @param key A key string. + * @param value An object which is the value. It should be of one of these * types: Boolean, Double, Integer, JSONArray, JSONObject, Long, * String, or the JSONObject.NULL object. * @return this. - * @throws JSONException - * If the value is a non-finite number. + * @throws JSONException If the value is a non-finite number. */ - public JSONObject putOpt(String key, Object value) throws JSONException { - if (key != null && value != null) { + public JSONObject putOpt(final String key, final Object value) + throws JSONException + { + if (key != null && value != null) this.put(key, value); - } return this; } @@ -1324,23 +1216,24 @@ public JSONObject putOpt(String key, Object value) throws JSONException { * allowing JSON text to be delivered in HTML. In JSON text, a string cannot * contain a control character or an unescaped quote or backslash. * - * @param string - * A String + * @param string A String * @return A String correctly formatted for insertion in a JSON text. */ - public static String quote(String string) { - StringWriter sw = new StringWriter(); + public static String quote(final String string) { + final StringWriter sw = new StringWriter(); synchronized (sw.getBuffer()) { try { return quote(string, sw).toString(); - } catch (IOException ignored) { + } catch (final IOException ignored) { // will never happen - we are writing to a string writer return ""; } } } - public static Writer quote(String string, Writer w) throws IOException { + public static Writer quote(final String string, final Writer w) + throws IOException + { if (string == null || string.length() == 0) { w.write("\"\""); return w; @@ -1350,49 +1243,49 @@ public static Writer quote(String string, Writer w) throws IOException { char c = 0; String hhhh; int i; - int len = string.length(); + final int len = string.length(); w.write('"'); for (i = 0; i < len; i += 1) { b = c; c = string.charAt(i); switch (c) { - case '\\': - case '"': - w.write('\\'); - w.write(c); - break; - case '/': - if (b == '<') { + case '\\': + case '"': w.write('\\'); - } - w.write(c); - break; - case '\b': - w.write("\\b"); - break; - case '\t': - w.write("\\t"); - break; - case '\n': - w.write("\\n"); - break; - case '\f': - w.write("\\f"); - break; - case '\r': - w.write("\\r"); - break; - default: - if (c < ' ' || (c >= '\u0080' && c < '\u00a0') - || (c >= '\u2000' && c < '\u2100')) { - w.write("\\u"); - hhhh = Integer.toHexString(c); - w.write("0000", 0, 4 - hhhh.length()); - w.write(hhhh); - } else { w.write(c); - } + break; + case '/': + if (b == '<') + w.write('\\'); + w.write(c); + break; + case '\b': + w.write("\\b"); + break; + case '\t': + w.write("\\t"); + break; + case '\n': + w.write("\\n"); + break; + case '\f': + w.write("\\f"); + break; + case '\r': + w.write("\\r"); + break; + default: + if (c < ' ' || c >= '\u0080' && c < '\u00a0' + || c >= '\u2000' && c < '\u2100') + { + w.write("\\u"); + hhhh = Integer.toHexString(c); + w.write("0000", 0, 4 - hhhh.length()); + w.write(hhhh); + } + else + w.write(c); } } w.write('"'); @@ -1402,51 +1295,46 @@ public static Writer quote(String string, Writer w) throws IOException { /** * Remove a name and its value, if present. * - * @param key - * The name to be removed. + * @param key The name to be removed. * @return The value that was associated with the name, or null if there was * no value. */ - public Object remove(String key) { + public Object remove(final String key) { return super.remove(key); } /** - * Determine if two JSONObjects are similar. - * They must contain the same set of names which must be associated with - * similar values. + * Determine if two JSONObjects are similar. They must contain the same set + * of names which must be associated with similar values. * * @param other The other JSONObject * @return true if they are equal */ - public boolean similar(Object other) { + public boolean similar(final Object other) { try { - if (!(other instanceof JSONObject)) { + if (!(other instanceof JSONObject)) return false; - } - Set set = keySet(); - if (!set.equals(((JSONObject)other).keySet())) { + final Set set = keySet(); + if (!set.equals(((JSONObject)other).keySet())) return false; - } - Iterator iterator = set.iterator(); + final Iterator iterator = set.iterator(); while (iterator.hasNext()) { - String name = iterator.next(); - Object valueThis = this.get(name); - Object valueOther = ((JSONObject)other).get(name); + final String name = iterator.next(); + final Object valueThis = this.get(name); + final Object valueOther = ((JSONObject)other).get(name); if (valueThis instanceof JSONObject) { - if (!((JSONObject)valueThis).similar(valueOther)) { + if (!((JSONObject)valueThis).similar(valueOther)) return false; - } - } else if (valueThis instanceof JSONArray) { - if (!((JSONArray)valueThis).similar(valueOther)) { + } + else if (valueThis instanceof JSONArray) { + if (!((JSONArray)valueThis).similar(valueOther)) return false; - } - } else if (!valueThis.equals(valueOther)) { - return false; } + else if (!valueThis.equals(valueOther)) + return false; } return true; - } catch (Throwable exception) { + } catch (final Throwable exception) { return false; } } @@ -1455,98 +1343,81 @@ public boolean similar(Object other) { * Try to convert a string into a number, boolean, or null. If the string * can't be converted, return the string. * - * @param string - * A String. + * @param string A String. * @return A simple JSON value. */ - public static Object stringToValue(String string) { + public static Object stringToValue(final String string) { Double d; - if (string.equals("")) { + if (string.equals("")) return string; - } - if (string.equalsIgnoreCase("true")) { + if (string.equalsIgnoreCase("true")) return Boolean.TRUE; - } - if (string.equalsIgnoreCase("false")) { + if (string.equalsIgnoreCase("false")) return Boolean.FALSE; - } - if (string.equalsIgnoreCase("null")) { + if (string.equalsIgnoreCase("null")) return JSONObject.NULL; - } /* * If it might be a number, try converting it. If a number cannot be * produced, then the value will just be a string. */ - char b = string.charAt(0); - if ((b >= '0' && b <= '9') || b == '-') { + final char b = string.charAt(0); + if (b >= '0' && b <= '9' || b == '-') try { if (string.indexOf('.') > -1 || string.indexOf('e') > -1 - || string.indexOf('E') > -1) { + || string.indexOf('E') > -1) + { d = Double.valueOf(string); - if (!d.isInfinite() && !d.isNaN()) { + if (!d.isInfinite() && !d.isNaN()) return d; - } - } else { - Long myLong = new Long(string); - if (string.equals(myLong.toString())) { - if (myLong == myLong.intValue()) { + } + else { + final Long myLong = new Long(string); + if (string.equals(myLong.toString())) + if (myLong == myLong.intValue()) return myLong.intValue(); - } else { + else return myLong; - } - } } - } catch (Exception ignore) { - } - } + } catch (final Exception ignore) {} return string; } /** * Throw an exception if the object is a NaN or infinite number. * - * @param o - * The object to test. - * @throws JSONException - * If o is a non-finite number. + * @param o The object to test. + * @throws JSONException If o is a non-finite number. */ - public static void testValidity(Object o) throws JSONException { - if (o != null) { + public static void testValidity(final Object o) throws JSONException { + if (o != null) if (o instanceof Double) { - if (((Double) o).isInfinite() || ((Double) o).isNaN()) { + if (((Double)o).isInfinite() || ((Double)o).isNaN()) throw new JSONException( - "JSON does not allow non-finite numbers."); - } - } else if (o instanceof Float) { - if (((Float) o).isInfinite() || ((Float) o).isNaN()) { - throw new JSONException( - "JSON does not allow non-finite numbers."); - } + "JSON does not allow non-finite numbers."); } - } + else if (o instanceof Float) + if (((Float)o).isInfinite() || ((Float)o).isNaN()) + throw new JSONException( + "JSON does not allow non-finite numbers."); } /** * Produce a JSONArray containing the values of the members of this * JSONObject. * - * @param names - * A JSONArray containing a list of key strings. This determines - * the sequence of the values in the result. + * @param names A JSONArray containing a list of key strings. This + * determines the sequence of the values in the result. * @return A JSONArray of values. - * @throws JSONException - * If any of the values are non-finite numbers. + * @throws JSONException If any of the values are non-finite numbers. */ - public JSONArray toJSONArray(JSONArray names) throws JSONException { - if (names == null || names.length() == 0) { + public JSONArray toJSONArray(final JSONArray names) throws JSONException { + if (names == null || names.length() == 0) return null; - } - JSONArray ja = new JSONArray(); - for (int i = 0; i < names.length(); i += 1) { + final JSONArray ja = new JSONArray(); + for (int i = 0; i < names.length(); i += 1) ja.put(opt(names.getString(i))); - } return ja; } @@ -1566,7 +1437,7 @@ public JSONArray toJSONArray(JSONArray names) throws JSONException { public String toString() { try { return this.toString(0); - } catch (Exception e) { + } catch (final Exception e) { return null; } } @@ -1576,17 +1447,16 @@ public String toString() { *

    * Warning: This method assumes that the data structure is acyclical. * - * @param indentFactor - * The number of spaces to add to each level of indentation. + * @param indentFactor The number of spaces to add to each level of + * indentation. * @return a printable, displayable, portable, transmittable representation * of the object, beginning with { (left * brace) and ending with } (right * brace). - * @throws JSONException - * If the object contains an invalid number. + * @throws JSONException If the object contains an invalid number. */ - public String toString(int indentFactor) throws JSONException { - StringWriter w = new StringWriter(); + public String toString(final int indentFactor) throws JSONException { + final StringWriter w = new StringWriter(); synchronized (w.getBuffer()) { return this.write(w, indentFactor, 0).toString(); } @@ -1603,53 +1473,47 @@ public String toString(int indentFactor) throws JSONException { * JSONObject will be made from it and its toJSONString method will be * called. Otherwise, the value's toString method will be called, and the * result will be quoted. - * *

    * Warning: This method assumes that the data structure is acyclical. * - * @param value - * The value to be serialized. + * @param value The value to be serialized. * @return a printable, displayable, transmittable representation of the * object, beginning with { (left * brace) and ending with } (right * brace). - * @throws JSONException - * If the value is or contains an invalid number. + * @throws JSONException If the value is or contains an invalid number. */ - public static String valueToString(Object value) throws JSONException { - if (value == null || value.equals(null)) { + public static String valueToString(final Object value) + throws JSONException + { + if (value == null || value.equals(null)) return "null"; - } if (value instanceof JSONString) { Object object; try { - object = ((JSONString) value).toJSONString(); - } catch (Exception e) { + object = ((JSONString)value).toJSONString(); + } catch (final Exception e) { throw new JSONException(e); } - if (object instanceof String) { - return (String) object; - } + if (object instanceof String) + return (String)object; throw new JSONException("Bad value from toJSONString: " + object); } - if (value instanceof Number) { - return numberToString((Number) value); - } + if (value instanceof Number) + return numberToString((Number)value); if (value instanceof Boolean || value instanceof JSONObject - || value instanceof JSONArray) { + || value instanceof JSONArray) return value.toString(); - } if (value instanceof Map) { - Map map = (Map) value; + final Map map = (Map)value; return new JSONObject(map).toString(); } if (value instanceof Collection) { - Collection coll = (Collection) value; + final Collection coll = (Collection)value; return new JSONArray(coll).toString(); } - if (value.getClass().isArray()) { + if (value.getClass().isArray()) return new JSONArray(value).toString(); - } return quote(value.toString()); } @@ -1661,47 +1525,42 @@ public static String valueToString(Object value) throws JSONException { * one of the java packages, turn it into a string. And if it doesn't, try * to wrap it in a JSONObject. If the wrapping fails, then null is returned. * - * @param object - * The object to wrap + * @param object The object to wrap * @return The wrapped value */ - public static Object wrap(Object object) { + public static Object wrap(final Object object) { try { - if (object == null) { + if (object == null) return NULL; - } if (object instanceof JSONObject || object instanceof JSONArray - || NULL.equals(object) || object instanceof JSONString - || object instanceof Byte || object instanceof Character - || object instanceof Short || object instanceof Integer - || object instanceof Long || object instanceof Boolean - || object instanceof Float || object instanceof Double - || object instanceof String || object instanceof BigInteger - || object instanceof BigDecimal) { + || NULL.equals(object) || object instanceof JSONString + || object instanceof Byte || object instanceof Character + || object instanceof Short || object instanceof Integer + || object instanceof Long || object instanceof Boolean + || object instanceof Float || object instanceof Double + || object instanceof String || object instanceof BigInteger + || object instanceof BigDecimal) return object; - } if (object instanceof Map) { - Map map = (Map) object; + final Map map = (Map)object; return new JSONObject(map); } if (object instanceof Collection) { - Collection coll = (Collection) object; + final Collection coll = (Collection)object; return new JSONArray(coll); } - if (object.getClass().isArray()) { + if (object.getClass().isArray()) return new JSONArray(object); - } - Package objectPackage = object.getClass().getPackage(); - String objectPackageName = objectPackage != null ? objectPackage - .getName() : ""; + final Package objectPackage = object.getClass().getPackage(); + final String objectPackageName = objectPackage != null + ? objectPackage.getName() : ""; if (objectPackageName.startsWith("java.") - || objectPackageName.startsWith("javax.") - || object.getClass().getClassLoader() == null) { + || objectPackageName.startsWith("javax.") + || object.getClass().getClassLoader() == null) return object.toString(); - } return new JSONObject(object); - } catch (Exception exception) { + } catch (final Exception exception) { return null; } } @@ -1711,52 +1570,58 @@ public static Object wrap(Object object) { * compactness, no whitespace is added. *

    * Warning: This method assumes that the data structure is acyclical. - * + * + * @param writer The writer * @return The writer. - * @throws JSONException + * @throws JSONException If there was an error in writing */ - public Writer write(Writer writer) throws JSONException { + public Writer write(final 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 == null || value.equals(null)) { + static final Writer writeValue(final Writer writer, final Object value, + final int indentFactor, final int indent) + throws JSONException, IOException + { + if (value == null || value.equals(null)) writer.write("null"); - } else 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) { - Map map = (Map) value; + else 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) { + final Map map = (Map)value; new JSONObject(map).write(writer, indentFactor, indent); - } else if (value instanceof Collection) { - Collection coll = (Collection) value; + } + else if (value instanceof Collection) { + final Collection coll = (Collection)value; new JSONArray(coll).write(writer, indentFactor, indent); - } else if (value.getClass().isArray()) { + } + 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) { + else if (value instanceof Number) + writer.write(numberToString((Number)value)); + else if (value instanceof Boolean) writer.write(value.toString()); - } else if (value instanceof JSONString) { + else if (value instanceof JSONString) { Object o; try { - o = ((JSONString) value).toJSONString(); - } catch (Exception e) { + o = ((JSONString)value).toJSONString(); + } catch (final Exception e) { throw new JSONException(e); } writer.write(o != null ? o.toString() : quote(value.toString())); - } else { - quote(value.toString(), writer); } + 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) { + static final void indent(final Writer writer, final int indent) + throws IOException + { + for (int i = 0; i < indent; i += 1) writer.write(' '); - } } /** @@ -1765,58 +1630,53 @@ static final void indent(Writer writer, int indent) throws IOException { *

    * Warning: This method assumes that the data structure is acyclical. * - * @param writer - * Writes the serialized JSON - * @param indentFactor - * The number of spaces to add to each level of indentation. - * @param indent - * The indention of the top level. + * @param writer Writes the serialized JSON + * @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 + * @throws JSONException If there was an error during writing */ - public Writer write(Writer writer, int indentFactor, int indent) - throws JSONException { + public Writer write(final Writer writer, final int indentFactor, + final int indent) throws JSONException + { try { boolean commanate = false; final int length = length(); - Iterator keys = keys(); + final Iterator keys = keys(); writer.write('{'); if (length == 1) { - Object key = keys.next(); + final Object key = keys.next(); writer.write(quote(key.toString())); writer.write(':'); - if (indentFactor > 0) { + if (indentFactor > 0) writer.write(' '); - } writeValue(writer, super.get(key), indentFactor, indent); - } else if (length != 0) { + } + else if (length != 0) { final int newindent = indent + indentFactor; while (keys.hasNext()) { - Object key = keys.next(); - if (commanate) { + final Object key = keys.next(); + if (commanate) writer.write(','); - } - if (indentFactor > 0) { + if (indentFactor > 0) writer.write('\n'); - } indent(writer, newindent); writer.write(quote(key.toString())); writer.write(':'); - if (indentFactor > 0) { + if (indentFactor > 0) writer.write(' '); - } writeValue(writer, super.get(key), indentFactor, newindent); commanate = true; } - if (indentFactor > 0) { + if (indentFactor > 0) writer.write('\n'); - } indent(writer, indent); } writer.write('}'); return writer; - } catch (IOException exception) { + } catch (final IOException exception) { throw new JSONException(exception); } } diff --git a/JSONTokener.java b/JSONTokener.java index 32548ed9f..f9352b02a 100644 --- a/JSONTokener.java +++ b/JSONTokener.java @@ -1,11 +1,6 @@ package org.json; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; +import java.io.*; /* Copyright (c) 2002 JSON.org @@ -33,337 +28,327 @@ of this software and associated documentation files (the "Software"), to deal /** * A JSONTokener takes a source string and extracts characters and tokens from - * it. It is used by the JSONObject and JSONArray constructors to parse - * JSON source strings. + * it. It is used by the JSONObject and JSONArray constructors to parse JSON + * source strings. + * * @author JSON.org * @version 2014-05-03 */ public class JSONTokener { - private long character; + private long character; private boolean eof; - private long index; - private long line; - private char previous; - private Reader reader; + private long index; + private long line; + private char previous; + private final Reader reader; private boolean usePrevious; - /** * Construct a JSONTokener from a Reader. * - * @param reader A reader. + * @param reader A reader. */ - public JSONTokener(Reader reader) { - this.reader = reader.markSupported() - ? reader + public JSONTokener(final Reader reader) { + this.reader = reader.markSupported() ? reader : new BufferedReader(reader); - this.eof = false; - this.usePrevious = false; - this.previous = 0; - this.index = 0; - this.character = 1; - this.line = 1; + eof = false; + usePrevious = false; + previous = 0; + index = 0; + character = 1; + line = 1; } - /** * Construct a JSONTokener from an InputStream. + * * @param inputStream The source. + * @throws JSONException If something goes wrong */ - public JSONTokener(InputStream inputStream) throws JSONException { + public JSONTokener(final InputStream inputStream) throws JSONException { this(new InputStreamReader(inputStream)); } - /** * Construct a JSONTokener from a string. * - * @param s A source string. + * @param s A source string. */ - public JSONTokener(String s) { + public JSONTokener(final String s) { this(new StringReader(s)); } - /** - * Back up one character. This provides a sort of lookahead capability, - * so that you can test for a digit or letter before attempting to parse - * the next number or identifier. + * Back up one character. This provides a sort of lookahead capability, so + * that you can test for a digit or letter before attempting to parse the + * next number or identifier. + * + * @throws JSONException If something goes wrong */ public void back() throws JSONException { - if (this.usePrevious || this.index <= 0) { + if (usePrevious || index <= 0) throw new JSONException("Stepping back two steps is not supported"); - } - this.index -= 1; - this.character -= 1; - this.usePrevious = true; - this.eof = false; + index -= 1; + character -= 1; + usePrevious = true; + eof = false; } - /** * Get the hex value of a character (base16). + * * @param c A character between '0' and '9' or between 'A' and 'F' or - * between 'a' and 'f'. - * @return An int between 0 and 15, or -1 if c was not a hex digit. + * between 'a' and 'f'. + * @return An int between 0 and 15, or -1 if c was not a hex digit. */ - public static int dehexchar(char c) { - if (c >= '0' && c <= '9') { + public static int dehexchar(final char c) { + if (c >= '0' && c <= '9') return c - '0'; - } - if (c >= 'A' && c <= 'F') { + if (c >= 'A' && c <= 'F') return c - ('A' - 10); - } - if (c >= 'a' && c <= 'f') { + if (c >= 'a' && c <= 'f') return c - ('a' - 10); - } return -1; } public boolean end() { - return this.eof && !this.usePrevious; + return eof && !usePrevious; } - /** - * Determine if the source string still contains characters that next() - * can consume. + * Determine if the source string still contains characters that next() can + * consume. + * * @return true if not yet at the end of the source. + * @throws JSONException If something goes wrong */ public boolean more() throws JSONException { this.next(); - if (this.end()) { + if (end()) return false; - } - this.back(); + back(); return true; } - /** * Get the next character in the source string. * * @return The next character, or 0 if past the end of the source string. + * @throws JSONException If something goes wrong */ public char next() throws JSONException { int c; - if (this.usePrevious) { - this.usePrevious = false; - c = this.previous; - } else { + if (usePrevious) { + usePrevious = false; + c = previous; + } + else { try { - c = this.reader.read(); - } catch (IOException exception) { + c = reader.read(); + } catch (final IOException exception) { throw new JSONException(exception); } if (c <= 0) { // End of stream - this.eof = true; + eof = true; c = 0; } } - this.index += 1; - if (this.previous == '\r') { - this.line += 1; - this.character = c == '\n' ? 0 : 1; - } else if (c == '\n') { - this.line += 1; - this.character = 0; - } else { - this.character += 1; + index += 1; + if (previous == '\r') { + line += 1; + character = c == '\n' ? 0 : 1; } - this.previous = (char) c; - return this.previous; + else if (c == '\n') { + line += 1; + character = 0; + } + else + character += 1; + previous = (char)c; + return previous; } - /** * Consume the next character, and check that it matches a specified * character. + * * @param c The character to match. * @return The character. * @throws JSONException if the character does not match. */ - public char next(char c) throws JSONException { - char n = this.next(); - if (n != c) { - throw this.syntaxError("Expected '" + c + "' and instead saw '" + - n + "'"); - } + public char next(final char c) throws JSONException { + final char n = this.next(); + if (n != c) + throw syntaxError( + "Expected '" + c + "' and instead saw '" + n + "'"); return n; } - /** * Get the next n characters. * - * @param n The number of characters to take. - * @return A string of n characters. - * @throws JSONException - * Substring bounds error if there are not - * n characters remaining in the source string. + * @param n The number of characters to take. + * @return A string of n characters. + * @throws JSONException Substring bounds error if there are not n + * characters remaining in the source string. */ - public String next(int n) throws JSONException { - if (n == 0) { - return ""; - } - - char[] chars = new char[n]; - int pos = 0; - - while (pos < n) { - chars[pos] = this.next(); - if (this.end()) { - throw this.syntaxError("Substring bounds error"); - } - pos += 1; - } - return new String(chars); - } - + public String next(final int n) throws JSONException { + if (n == 0) + return ""; + + final char[] chars = new char[n]; + int pos = 0; + + while (pos < n) { + chars[pos] = this.next(); + if (end()) + throw syntaxError("Substring bounds error"); + pos += 1; + } + return new String(chars); + } /** * Get the next char in the string, skipping whitespace. - * @throws JSONException - * @return A character, or 0 if there are no more characters. + * + * @throws JSONException If something goes wrong + * @return A character, or 0 if there are no more characters. */ public char nextClean() throws JSONException { for (;;) { - char c = this.next(); - if (c == 0 || c > ' ') { + final char c = this.next(); + if (c == 0 || c > ' ') return c; - } } } - /** - * Return the characters up to the next close quote character. - * Backslash processing is done. The formal JSON format does not - * allow strings in single quotes, but an implementation is allowed to - * accept them. - * @param quote The quoting character, either - * " (double quote) or - * ' (single quote). - * @return A String. + * Return the characters up to the next close quote character. Backslash + * processing is done. The formal JSON format does not allow strings in + * single quotes, but an implementation is allowed to accept them. + * + * @param quote The quoting character, either "  + * (double quote) or '  + * (single quote). + * @return A String. * @throws JSONException Unterminated string. */ - public String nextString(char quote) throws JSONException { + public String nextString(final char quote) throws JSONException { char c; - StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(); for (;;) { c = this.next(); switch (c) { - case 0: - case '\n': - case '\r': - throw this.syntaxError("Unterminated string"); - case '\\': - c = this.next(); - switch (c) { - case 'b': - sb.append('\b'); - break; - case 't': - sb.append('\t'); - break; - case 'n': - sb.append('\n'); - break; - case 'f': - sb.append('\f'); - break; - case 'r': - sb.append('\r'); - break; - case 'u': - sb.append((char)Integer.parseInt(this.next(4), 16)); - break; - case '"': - case '\'': + case 0: + case '\n': + case '\r': + throw syntaxError("Unterminated string"); case '\\': - case '/': - sb.append(c); + c = this.next(); + switch (c) { + case 'b': + sb.append('\b'); + break; + case 't': + sb.append('\t'); + break; + case 'n': + sb.append('\n'); + break; + case 'f': + sb.append('\f'); + break; + case 'r': + sb.append('\r'); + break; + case 'u': + sb.append((char)Integer.parseInt(this.next(4), 16)); + break; + case '"': + case '\'': + case '\\': + case '/': + sb.append(c); + break; + default: + throw syntaxError("Illegal escape."); + } break; default: - throw this.syntaxError("Illegal escape."); - } - break; - default: - if (c == quote) { - return sb.toString(); - } - sb.append(c); + if (c == quote) + return sb.toString(); + sb.append(c); } } } - /** - * Get the text up but not including the specified character or the - * end of line, whichever comes first. - * @param delimiter A delimiter character. - * @return A string. + * Get the text up but not including the specified character or the end of + * line, whichever comes first. + * + * @param delimiter A delimiter character. + * @return A string. + * @throws JSONException If something goes wrong */ - public String nextTo(char delimiter) throws JSONException { - StringBuilder sb = new StringBuilder(); + public String nextTo(final char delimiter) throws JSONException { + final StringBuilder sb = new StringBuilder(); for (;;) { - char c = this.next(); + final char c = this.next(); if (c == delimiter || c == 0 || c == '\n' || c == '\r') { - if (c != 0) { - this.back(); - } + if (c != 0) + back(); return sb.toString().trim(); } sb.append(c); } } - /** * Get the text up but not including one of the specified delimiter * characters or the end of line, whichever comes first. + * * @param delimiters A set of delimiter characters. * @return A string, trimmed. + * @throws JSONException If something goes wrong */ - public String nextTo(String delimiters) throws JSONException { + public String nextTo(final String delimiters) throws JSONException { char c; - StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(); for (;;) { c = this.next(); - if (delimiters.indexOf(c) >= 0 || c == 0 || - c == '\n' || c == '\r') { - if (c != 0) { - this.back(); - } + if (delimiters.indexOf(c) >= 0 || c == 0 || c == '\n' + || c == '\r') + { + if (c != 0) + back(); return sb.toString().trim(); } sb.append(c); } } - /** * Get the next value. The value can be a Boolean, Double, Integer, * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. - * @throws JSONException If syntax error. * + * @throws JSONException If syntax error. * @return An object. */ public Object nextValue() throws JSONException { - char c = this.nextClean(); + char c = nextClean(); String string; switch (c) { case '"': case '\'': - return this.nextString(c); + return nextString(c); case '{': - this.back(); + back(); return new JSONObject(this); case '[': - this.back(); + back(); return new JSONArray(this); } @@ -376,71 +361,70 @@ public Object nextValue() throws JSONException { * formatting character. */ - StringBuilder sb = new StringBuilder(); + final StringBuilder sb = new StringBuilder(); while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { sb.append(c); c = this.next(); } - this.back(); + back(); string = sb.toString().trim(); - if ("".equals(string)) { - throw this.syntaxError("Missing value"); - } + if ("".equals(string)) + throw syntaxError("Missing value"); return JSONObject.stringToValue(string); } - /** - * Skip characters until the next character is the requested character. - * If the requested character is not found, no characters are skipped. + * Skip characters until the next character is the requested character. If + * the requested character is not found, no characters are skipped. + * * @param to A character to skip to. - * @return The requested character, or zero if the requested character - * is not found. + * @return The requested character, or zero if the requested character is + * not found. + * @throws JSONException If something goes wrong */ - public char skipTo(char to) throws JSONException { + public char skipTo(final char to) throws JSONException { char c; try { - long startIndex = this.index; - long startCharacter = this.character; - long startLine = this.line; - this.reader.mark(1000000); + final long startIndex = index; + final long startCharacter = character; + final long startLine = line; + reader.mark(1000000); do { c = this.next(); if (c == 0) { - this.reader.reset(); - this.index = startIndex; - this.character = startCharacter; - this.line = startLine; + reader.reset(); + index = startIndex; + character = startCharacter; + line = startLine; return c; } } while (c != to); - } catch (IOException exception) { + } catch (final IOException exception) { throw new JSONException(exception); } - this.back(); + back(); return c; } - /** * Make a JSONException to signal a syntax error. * * @param message The error message. - * @return A JSONException object, suitable for throwing + * @return A JSONException object, suitable for throwing */ - public JSONException syntaxError(String message) { - return new JSONException(message + this.toString()); + public JSONException syntaxError(final String message) { + return new JSONException(message + toString()); } - /** * Make a printable string of this JSONTokener. * * @return " at {index} [character {character} line {line}]" */ + @Override public String toString() { - return " at " + this.index + " [character " + this.character + " line " + - this.line + "]"; + return " at " + index + " [character " + character + " line " + line + + "]"; } } diff --git a/JSONWriter.java b/JSONWriter.java index a67291907..541a0c133 100644 --- a/JSONWriter.java +++ b/JSONWriter.java @@ -29,47 +29,46 @@ of this software and associated documentation files (the "Software"), to deal */ /** - * JSONWriter provides a quick and convenient way of producing JSON text. - * The texts produced strictly conform to JSON syntax rules. No whitespace is - * added, so the results are ready for transmission or storage. Each instance of + * JSONWriter provides a quick and convenient way of producing JSON text. The + * texts produced strictly conform to JSON syntax rules. No whitespace is added, + * so the results are ready for transmission or storage. Each instance of * JSONWriter can produce one JSON text. *

    * A JSONWriter instance provides a value method for appending - * values to the - * text, and a key - * method for adding keys before values in objects. There are array - * and endArray methods that make and bound array values, and - * object and endObject methods which make and bound - * object values. All of these methods return the JSONWriter instance, - * permitting a cascade style. For example,

    - * new JSONWriter(myWriter)
    - *     .object()
    - *         .key("JSON")
    - *         .value("Hello, World!")
    - *     .endObject();
    which writes
    - * {"JSON":"Hello, World!"}
    + * values to the text, and a key method for adding keys before + * values in objects. There are array and endArray + * methods that make and bound array values, and object and + * endObject methods which make and bound object values. All of + * these methods return the JSONWriter instance, permitting a cascade style. For + * example, + * + *
    + * new JSONWriter(myWriter).object().key("JSON").value("Hello, World!")
    + *     .endObject();
    + * 
    + * + * which writes + * + *
    + * {"JSON":"Hello, World!"}
    + * 
    *

    * The first method called must be array or object. * There are no methods for adding commas or colons. JSONWriter adds them for * you. *

    * This can sometimes be easier than using a JSONObject to build a string. + * * @author JSON.org * @version 2015-12-09 */ public class JSONWriter { /** - * The current mode. Values: - * 'a' (array), - * 'A' (array after first element), - * 'i' (initial/done), - * 'k' (object: key), - * 'o' (object: value), - * 'K' (object: key after first element). - * - * The stack top is completely determined by the mode: it is empty in modes - * 'i', 'd', true (object) in modes 'k', 'o', 'K', and false (array) in - * modes 'a', 'A'. + * The current mode. Values: 'a' (array), 'A' (array after first element), + * 'i' (initial/done), 'k' (object: key), 'o' (object: value), 'K' (object: + * key after first element). The stack top is completely determined by the + * mode: it is empty in modes 'i', 'd', true (object) in modes 'k', 'o', + * 'K', and false (array) in modes 'a', 'A'. */ protected char mode; @@ -91,8 +90,10 @@ public class JSONWriter { /** * Make a fresh JSONWriter. It can be used to build one JSON text. + * + * @param w The base writer */ - public JSONWriter(Writer w) { + public JSONWriter(final Writer w) { mode = 'i'; stack = new BitSet(); top = 0; @@ -101,41 +102,39 @@ public JSONWriter(Writer w) { /** * Append a value. + * * @param string A string value. * @return this * @throws JSONException If the value is out of sequence. */ - private JSONWriter append(String string) throws JSONException { - if (string == null) { + private JSONWriter append(final String string) throws JSONException { + if (string == null) throw new JSONException("Null pointer"); - } - if (mode == 'd') { + if (mode == 'd') throw new JSONException("Value out of sequence."); - } try { - if (mode == 'A' || mode == 'K') { + if (mode == 'A' || mode == 'K') writer.write(','); - } else if (mode == 'o') { + else if (mode == 'o') writer.write(':'); - } writer.write(string); - } catch (IOException e) { + } catch (final IOException e) { throw new JSONException(e); } switch (mode) { - case 'a': - mode = 'A'; - break; - case 'k': - case 'K': - mode = 'o'; - break; - case 'o': - mode = 'K'; - break; - case 'i': - mode = 'd'; - break; + case 'a': + mode = 'A'; + break; + case 'k': + case 'K': + mode = 'o'; + break; + case 'o': + mode = 'K'; + break; + case 'i': + mode = 'd'; + break; } return this; } @@ -144,10 +143,11 @@ private JSONWriter append(String string) throws JSONException { * Begin appending a new array. All values until the balancing * endArray will be appended to this array. The * endArray method must be called to mark the array's end. + * * @return this * @throws JSONException If the nesting is too deep, or if the object is - * started in the wrong place (for example as a key or after the end of the - * outermost array or object). + * started in the wrong place (for example as a key or after the + * end of the outermost array or object). */ public JSONWriter array() throws JSONException { if (mode == 'i' || mode == 'o' || mode == 'a' || mode == 'A') { @@ -160,16 +160,16 @@ public JSONWriter array() throws JSONException { /** * End something. - * @param mode Mode + * * @param c Closing character * @return this * @throws JSONException If unbalanced. */ - private JSONWriter end(char c) throws JSONException { + private JSONWriter end(final char c) throws JSONException { pop(); try { writer.write(c); - } catch (IOException e) { + } catch (final IOException e) { throw new JSONException(e); } return this; @@ -178,79 +178,79 @@ private JSONWriter end(char c) throws JSONException { /** * End an array. This method most be called to balance calls to * array. + * * @return this * @throws JSONException If incorrectly nested. */ public JSONWriter endArray() throws JSONException { - if (mode != 'a' && mode != 'A') { + if (mode != 'a' && mode != 'A') throw new JSONException("Misplaced endArray."); - } return end(']'); } /** * End an object. This method most be called to balance calls to * object. + * * @return this * @throws JSONException If incorrectly nested. */ public JSONWriter endObject() throws JSONException { - if (mode != 'k' && mode != 'K') { + if (mode != 'k' && mode != 'K') throw new JSONException("Misplaced endObject."); - } return end('}'); } /** * End an object or array. This method most be called to balance calls to * object or array. + * * @return this * @throws JSONException If incorrectly nested. */ - public JSONWriter end() throws JSONException { - char bracket; - switch (mode) { - case 'a': - case 'A': - bracket = ']'; - break; - case 'k': - case 'K': - bracket = '}'; - break; - default: - throw new JSONException("Misplaced end."); - } - return end(bracket); - } + public JSONWriter end() throws JSONException { + char bracket; + switch (mode) { + case 'a': + case 'A': + bracket = ']'; + break; + case 'k': + case 'K': + bracket = '}'; + break; + default: + throw new JSONException("Misplaced end."); + } + return end(bracket); + } /** * Append a key. The key will be associated with the next value. In an * object, every value must be preceded by a key. + * * @param string A key string. * @return this - * @throws JSONException If the key is out of place. For example, keys - * do not belong in arrays or if the key is null. + * @throws JSONException If the key is out of place. For example, keys do + * not belong in arrays or if the key is null. */ - public JSONWriter key(String string) throws JSONException { - if (string == null) { + public JSONWriter key(final String string) throws JSONException { + if (string == null) throw new JSONException("Null key."); - } - if (mode == 'k' || mode == 'K') { + if (mode == 'k' || mode == 'K') return append(JSONObject.quote(string)); - } throw new JSONException("Misplaced key."); } - /** * Begin appending a new object. All keys and values until the balancing * endObject will be appended to this object. The * endObject method must be called to mark the object's end. + * * @return this * @throws JSONException If the nesting is too deep, or if the object is - * started in the wrong place (for example as a key or after the end of the - * outermost array or object). + * started in the wrong place (for example as a key or after the + * end of the outermost array or object). */ public JSONWriter object() throws JSONException { if (mode == 'i' || mode == 'o' || mode == 'a' || mode == 'A') { @@ -262,70 +262,73 @@ public JSONWriter object() throws JSONException { } - /** * Pop an array or object scope. + * * @throws JSONException If nesting is wrong. */ private void pop() throws JSONException { - if (top <= 0) { + if (top <= 0) throw new JSONException("Nesting error."); - } top--; mode = top == 0 ? 'd' : stack.get(top - 1) ? 'K' : 'A'; } /** * Push an array or object scope. + * * @param b The scope to open. * @throws JSONException If nesting is too deep. */ - private void push(boolean b) throws JSONException { + private void push(final boolean b) throws JSONException { stack.set(top++, b); mode = b ? 'k' : 'a'; } - /** - * Append either the value true or the value - * false. + * Append either the value true or the value false + * . + * * @param b A boolean. * @return this - * @throws JSONException + * @throws JSONException If something goes wrong */ - public JSONWriter value(boolean b) throws JSONException { + public JSONWriter value(final boolean b) throws JSONException { return append(b ? "true" : "false"); } /** * Append a double value. + * * @param d A double. * @return this * @throws JSONException If the number is not finite. */ - public JSONWriter value(double d) throws JSONException { + public JSONWriter value(final double d) throws JSONException { return value(new Double(d)); } /** * Append a long value. + * * @param l A long. * @return this - * @throws JSONException + * @throws JSONException If something goes wrong */ - public JSONWriter value(long l) throws JSONException { + public JSONWriter value(final long l) throws JSONException { return append(Long.toString(l)); } - /** * Append an object value. + * * @param object The object to append. It can be null, or a Boolean, Number, - * String, JSONObject, or JSONArray, or an object that implements JSONString. + * String, JSONObject, or JSONArray, or an object that implements + * JSONString. * @return this * @throws JSONException If the value is out of sequence. */ - public JSONWriter value(Object object) throws JSONException { + public JSONWriter value(final Object object) throws JSONException { return append(JSONObject.valueToString(object)); } } diff --git a/Property.java b/Property.java index 73ddb1287..3d6a78516 100644 --- a/Property.java +++ b/Property.java @@ -23,29 +23,31 @@ of this software and associated documentation files (the "Software"), to deal OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -import java.util.Enumeration; -import java.util.Iterator; -import java.util.Properties; +import java.util.*; /** * Converts a Property file data into JSONObject and back. + * * @author JSON.org * @version 2015-05-05 */ public class Property { /** - * Converts a property file object into a JSONObject. The property file object is a table of name value pairs. + * Converts a property file object into a JSONObject. The property file + * object is a table of name value pairs. + * * @param properties java.util.Properties * @return JSONObject - * @throws JSONException + * @throws JSONException If something goes wrong */ - public static JSONObject toJSONObject(java.util.Properties properties) throws JSONException { - JSONObject jo = new JSONObject(); + public static JSONObject toJSONObject(final java.util.Properties properties) + throws JSONException + { + final JSONObject jo = new JSONObject(); if (properties != null && !properties.isEmpty()) { - Enumeration enumProperties = properties.propertyNames(); - while(enumProperties.hasMoreElements()) { - String name = (String)enumProperties.nextElement(); + final Enumeration enumProperties = properties.propertyNames(); + while (enumProperties.hasMoreElements()) { + final String name = (String)enumProperties.nextElement(); jo.put(name, properties.getProperty(name)); } } @@ -54,16 +56,19 @@ public static JSONObject toJSONObject(java.util.Properties properties) throws JS /** * Converts the JSONObject into a property file object. + * * @param jo JSONObject * @return java.util.Properties - * @throws JSONException + * @throws JSONException If something goes wrong */ - public static Properties toProperties(JSONObject jo) throws JSONException { - Properties properties = new Properties(); + public static Properties toProperties(final JSONObject jo) + throws JSONException + { + final Properties properties = new Properties(); if (jo != null) { - Iterator keys = jo.keys(); + final Iterator keys = jo.keys(); while (keys.hasNext()) { - String name = keys.next(); + final String name = keys.next(); properties.put(name, jo.getString(name)); } } diff --git a/XML.java b/XML.java index f14463c94..1f5202dce 100644 --- a/XML.java +++ b/XML.java @@ -29,7 +29,7 @@ of this software and associated documentation files (the "Software"), to deal /** * This provides static methods to convert an XML text into a JSONObject, and to * covert a JSONObject into an XML text. - * + * * @author JSON.org * @version 2016-01-01 */ @@ -65,40 +65,39 @@ public class XML { /** * Replace special characters with XML escapes: - * + * *

          * & (ampersand) is replaced by &amp;
          * < (less than) is replaced by &lt;
          * > (greater than) is replaced by &gt;
          * " (double quote) is replaced by &quot;
          * 
    - * - * @param string - * The string to be escaped. + * + * @param string The string to be escaped. * @return The escaped string. */ - public static String escape(String string) { - StringBuilder sb = new StringBuilder(string.length()); + public static String escape(final String string) { + final StringBuilder sb = new StringBuilder(string.length()); for (int i = 0, length = string.length(); i < length; i++) { - char c = string.charAt(i); + final char c = string.charAt(i); switch (c) { - case '&': - sb.append("&"); - break; - case '<': - sb.append("<"); - break; - case '>': - sb.append(">"); - break; - case '"': - sb.append("""); - break; - case '\'': - sb.append("'"); - break; - default: - sb.append(c); + case '&': + sb.append("&"); + break; + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '"': + sb.append("""); + break; + case '\'': + sb.append("'"); + break; + default: + sb.append(c); } } return sb.toString(); @@ -107,38 +106,33 @@ public static String escape(String string) { /** * Throw an exception if the string contains whitespace. Whitespace is not * allowed in tagNames and attributes. - * - * @param string - * A string. - * @throws JSONException + * + * @param string A string. + * @throws JSONException If something goes wrong */ - public static void noSpace(String string) throws JSONException { - int i, length = string.length(); - if (length == 0) { + public static void noSpace(final String string) throws JSONException { + int i; + final int length = string.length(); + if (length == 0) throw new JSONException("Empty string."); - } - for (i = 0; i < length; i += 1) { - if (Character.isWhitespace(string.charAt(i))) { - throw new JSONException("'" + string - + "' contains a space character."); - } - } + for (i = 0; i < length; i += 1) + if (Character.isWhitespace(string.charAt(i))) + throw new JSONException( + "'" + string + "' contains a space character."); } /** * Scan the content following the named tag, attaching it to the context. - * - * @param x - * The XMLTokener containing the source string. - * @param context - * The JSONObject that will include the new material. - * @param name - * The tag name. + * + * @param x The XMLTokener containing the source string. + * @param context The JSONObject that will include the new material. + * @param name The tag name. * @return true if the close tag is processed. - * @throws JSONException + * @throws JSONException If something goes wrong */ - private static boolean parse(XMLTokener x, JSONObject context, String name) - throws JSONException { + private static boolean parse(final XMLTokener x, final JSONObject context, + final String name) throws JSONException + { char c; int i; JSONObject jsonobject = null; @@ -168,130 +162,121 @@ private static boolean parse(XMLTokener x, JSONObject context, String name) return false; } x.back(); - } else if (c == '[') { + } + else if (c == '[') { token = x.nextToken(); - if ("CDATA".equals(token)) { + if ("CDATA".equals(token)) if (x.next() == '[') { string = x.nextCDATA(); - if (string.length() > 0) { + if (string.length() > 0) context.accumulate("content", string); - } return false; } - } throw x.syntaxError("Expected 'CDATA['"); } i = 1; do { token = x.nextMeta(); - if (token == null) { + if (token == null) throw x.syntaxError("Missing '>' after ' 0); return false; - } else if (token == QUEST) { + } + else if (token == QUEST) { // "); return false; - } else if (token == SLASH) { + } + else if (token == SLASH) { // Close tag - if (x.nextToken() != GT) { + if (x.nextToken() != GT) throw x.syntaxError("Misshaped tag"); - } - if (jsonobject.length() > 0) { + if (jsonobject.length() > 0) context.accumulate(tagName, jsonobject); - } else { + else context.accumulate(tagName, ""); - } return false; - } else if (token == GT) { + } + else if (token == GT) // Content, between <...> and - for (;;) { + for (;;) + { token = x.nextContent(); if (token == null) { - if (tagName != null) { + if (tagName != null) throw x.syntaxError("Unclosed tag " + tagName); - } return false; - } else if (token instanceof String) { - string = (String) token; - if (string.length() > 0) { + } + else if (token instanceof String) { + string = (String)token; + if (string.length() > 0) jsonobject.accumulate("content", - XML.stringToValue(string)); - } + XML.stringToValue(string)); - } else if (token == LT) { + } + else if (token == LT) // Nested element - if (parse(x, jsonobject, tagName)) { - if (jsonobject.length() == 0) { + if (parse(x, jsonobject, tagName)) + { + if (jsonobject.length() == 0) context.accumulate(tagName, ""); - } else if (jsonobject.length() == 1 - && jsonobject.opt("content") != null) { + else if (jsonobject.length() == 1 + && jsonobject.opt("content") != null) context.accumulate(tagName, - jsonobject.opt("content")); - } else { + jsonobject.opt("content")); + else context.accumulate(tagName, jsonobject); - } return false; } - } } - } else { + else throw x.syntaxError("Misshaped tag"); - } } } } @@ -302,40 +287,33 @@ private static boolean parse(XMLTokener x, JSONObject context, String name) * JSONObject.stringToValue, especially because it does not attempt to * convert plus forms, octal forms, hex forms, or E forms lacking decimal * points. - * - * @param string - * A String. + * + * @param string A String. * @return A simple JSON value. */ - public static Object stringToValue(String string) { - if ("true".equalsIgnoreCase(string)) { + public static Object stringToValue(final String string) { + if ("true".equalsIgnoreCase(string)) return Boolean.TRUE; - } - if ("false".equalsIgnoreCase(string)) { + if ("false".equalsIgnoreCase(string)) return Boolean.FALSE; - } - if ("null".equalsIgnoreCase(string)) { + if ("null".equalsIgnoreCase(string)) return JSONObject.NULL; - } // If it might be a number, try converting it, first as a Long, and then // as a Double. If that doesn't work, return the string. try { - char initial = string.charAt(0); - if (initial == '-' || (initial >= '0' && initial <= '9')) { - Long value = new Long(string); - if (value.toString().equals(string)) { + final char initial = string.charAt(0); + if (initial == '-' || initial >= '0' && initial <= '9') { + final Long value = new Long(string); + if (value.toString().equals(string)) return value; - } } - } catch (Exception ignore) { + } catch (final Exception ignore) { try { - Double value = new Double(string); - if (value.toString().equals(string)) { + final Double value = new Double(string); + if (value.toString().equals(string)) return value; - } - } catch (Exception ignoreAlso) { - } + } catch (final Exception ignoreAlso) {} } return string; } @@ -350,46 +328,44 @@ public static Object stringToValue(String string) { * elements are represented as JSONArrays. Content text may be placed in a * "content" member. Comments, prologs, DTDs, and <[ [ ]]> * are ignored. - * - * @param string - * The source string. + * + * @param string The source string. * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException + * @throws JSONException If something goes wrong */ - public static JSONObject toJSONObject(String string) throws JSONException { - JSONObject jo = new JSONObject(); - XMLTokener x = new XMLTokener(string); - while (x.more() && x.skipPast("<")) { + public static JSONObject toJSONObject(final String string) + throws JSONException + { + final JSONObject jo = new JSONObject(); + final XMLTokener x = new XMLTokener(string); + while (x.more() && x.skipPast("<")) parse(x, jo, null); - } return jo; } /** * Convert a JSONObject into a well-formed, element-normal XML string. - * - * @param object - * A JSONObject. + * + * @param object A JSONObject. * @return A string. - * @throws JSONException + * @throws JSONException If something goes wrong */ - public static String toString(Object object) throws JSONException { + public static String toString(final Object object) throws JSONException { return toString(object, null); } /** * Convert a JSONObject into a well-formed, element-normal XML string. - * - * @param object - * A JSONObject. - * @param tagName - * The optional name of the enclosing tag. + * + * @param object A JSONObject. + * @param tagName The optional name of the enclosing tag. * @return A string. - * @throws JSONException + * @throws JSONException If something goes wrong */ - public static String toString(Object object, String tagName) - throws JSONException { - StringBuilder sb = new StringBuilder(); + public static String toString(Object object, final String tagName) + throws JSONException + { + final StringBuilder sb = new StringBuilder(); JSONArray ja; JSONObject jo; String key; @@ -407,39 +383,38 @@ public static String toString(Object object, String tagName) } // Loop thru the keys. - jo = (JSONObject) object; + jo = (JSONObject)object; keys = jo.keys(); while (keys.hasNext()) { key = keys.next(); value = jo.opt(key); - if (value == null) { + if (value == null) value = ""; - } else if (value.getClass().isArray()) { + else if (value.getClass().isArray()) value = new JSONArray(value); - } - string = value instanceof String ? (String) value : null; + string = value instanceof String ? (String)value : null; // Emit content in body if ("content".equals(key)) { if (value instanceof JSONArray) { - ja = (JSONArray) value; + ja = (JSONArray)value; int i = 0; - for (Object val : ja) { - if (i > 0) { + for (final Object val : ja) { + if (i > 0) sb.append('\n'); - } sb.append(escape(val.toString())); i++; } - } else { - sb.append(escape(value.toString())); } + else + sb.append(escape(value.toString())); // Emit an array of similar keys - } else if (value instanceof JSONArray) { - ja = (JSONArray) value; - for (Object val : ja) { + } + else if (value instanceof JSONArray) { + ja = (JSONArray)value; + for (final Object val : ja) if (val instanceof JSONArray) { sb.append('<'); sb.append(key); @@ -448,20 +423,20 @@ public static String toString(Object object, String tagName) sb.append("'); - } else { - sb.append(toString(val, key)); } - } - } else if ("".equals(value)) { + else + sb.append(toString(val, key)); + } + else if ("".equals(value)) { sb.append('<'); sb.append(key); sb.append("/>"); // Emit a new tag - } else { - sb.append(toString(value, key)); } + else + sb.append(toString(value, key)); } if (tagName != null) { @@ -475,26 +450,25 @@ public static String toString(Object object, String tagName) } if (object != null) { - if (object.getClass().isArray()) { + if (object.getClass().isArray()) object = new JSONArray(object); - } if (object instanceof JSONArray) { - ja = (JSONArray) object; - for (Object val : ja) { + ja = (JSONArray)object; + for (final Object val : ja) // XML does not have good support for arrays. If an array // appears in a place where XML is lacking, synthesize an // element. - sb.append(toString(val, tagName == null ? "array" : tagName)); - } + sb.append( + toString(val, tagName == null ? "array" : tagName)); return sb.toString(); } } - string = (object == null) ? "null" : escape(object.toString()); - return (tagName == null) ? "\"" + string + "\"" - : (string.length() == 0) ? "<" + tagName + "/>" : "<" + tagName - + ">" + string + ""; + string = object == null ? "null" : escape(object.toString()); + return tagName == null ? "\"" + string + "\"" + : string.length() == 0 ? "<" + tagName + "/>" + : "<" + tagName + ">" + string + ""; } } diff --git a/XMLTokener.java b/XMLTokener.java index e45e747dc..25332273a 100644 --- a/XMLTokener.java +++ b/XMLTokener.java @@ -25,194 +25,188 @@ of this software and associated documentation files (the "Software"), to deal */ /** - * The XMLTokener extends the JSONTokener to provide additional methods - * for the parsing of XML texts. + * The XMLTokener extends the JSONTokener to provide additional methods for the + * parsing of XML texts. + * * @author JSON.org * @version 2015-12-09 */ public class XMLTokener extends JSONTokener { - - /** The table of entity values. It initially contains Character values for - * amp, apos, gt, lt, quot. - */ - public static final java.util.HashMap entity; - - static { - entity = new java.util.HashMap(8); - entity.put("amp", XML.AMP); - entity.put("apos", XML.APOS); - entity.put("gt", XML.GT); - entity.put("lt", XML.LT); - entity.put("quot", XML.QUOT); - } + /** + * The table of entity values. It initially contains Character values for + * amp, apos, gt, lt, quot. + */ + public static final java.util.HashMap entity; + + static { + entity = new java.util.HashMap<>(8); + entity.put("amp", XML.AMP); + entity.put("apos", XML.APOS); + entity.put("gt", XML.GT); + entity.put("lt", XML.LT); + entity.put("quot", XML.QUOT); + } /** * Construct an XMLTokener from a string. + * * @param s A source string. */ - public XMLTokener(String s) { + public XMLTokener(final String s) { super(s); } /** * Get the text in the CDATA block. + * * @return The string up to the ]]>. * @throws JSONException If the ]]> is not found. */ public String nextCDATA() throws JSONException { - char c; - int i; - StringBuilder sb = new StringBuilder(); + char c; + int i; + final StringBuilder sb = new StringBuilder(); for (;;) { c = next(); - if (end()) { + if (end()) throw syntaxError("Unclosed CDATA"); - } sb.append(c); i = sb.length() - 3; - if (i >= 0 && sb.charAt(i) == ']' && - sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') { + if (i >= 0 && sb.charAt(i) == ']' && sb.charAt(i + 1) == ']' + && sb.charAt(i + 2) == '>') + { sb.setLength(i); return sb.toString(); } } } - /** - * Get the next XML outer token, trimming whitespace. There are two kinds - * of tokens: the '<' character which begins a markup tag, and the content - * text between markup tags. + * Get the next XML outer token, trimming whitespace. There are two kinds of + * tokens: the '<' character which begins a markup tag, and the content text + * between markup tags. * - * @return A string, or a '<' Character, or null if there is no more - * source text. - * @throws JSONException + * @return A string, or a '<' Character, or null if there is no more source + * text. + * @throws JSONException If something goes wrong */ public Object nextContent() throws JSONException { - char c; + char c; StringBuilder sb; - do { + do c = next(); - } while (Character.isWhitespace(c)); - if (c == 0) { + while (Character.isWhitespace(c)); + if (c == 0) return null; - } - if (c == '<') { + if (c == '<') return XML.LT; - } sb = new StringBuilder(); for (;;) { if (c == '<' || c == 0) { back(); return sb.toString().trim(); } - if (c == '&') { + if (c == '&') sb.append(nextEntity(c)); - } else { + else sb.append(c); - } c = next(); } } - /** * Return the next entity. These entities are translated to Characters: - * & ' > < ". + * & ' > < ". + * * @param ampersand An ampersand character. - * @return A Character or an entity String if the entity is not recognized. + * @return A Character or an entity String if the entity is not recognized. * @throws JSONException If missing ';' in XML entity. */ - public Object nextEntity(char ampersand) throws JSONException { - StringBuilder sb = new StringBuilder(); + public Object nextEntity(final char ampersand) throws JSONException { + final StringBuilder sb = new StringBuilder(); for (;;) { - char c = next(); - if (Character.isLetterOrDigit(c) || c == '#') { + final char c = next(); + if (Character.isLetterOrDigit(c) || c == '#') sb.append(Character.toLowerCase(c)); - } else if (c == ';') { + else if (c == ';') break; - } else { + else throw syntaxError("Missing ';' in XML entity: &" + sb); - } } - String string = sb.toString(); - Object object = entity.get(string); + final String string = sb.toString(); + final Object object = entity.get(string); return object != null ? object : ampersand + string + ";"; } - /** - * Returns the next XML meta token. This is used for skipping over - * and structures. + * Returns the next XML meta token. This is used for skipping over + * and structures. + * * @return Syntax characters (< > / = ! ?) are returned as - * Character, and strings and names are returned as Boolean. We don't care - * what the values actually are. - * @throws JSONException If a string is not properly closed or if the XML - * is badly structured. + * Character, and strings and names are returned as Boolean. We + * don't care what the values actually are. + * @throws JSONException If a string is not properly closed or if the XML is + * badly structured. */ public Object nextMeta() throws JSONException { char c; char q; - do { + do c = next(); - } while (Character.isWhitespace(c)); + while (Character.isWhitespace(c)); switch (c) { - case 0: - throw syntaxError("Misshaped meta tag"); - case '<': - return XML.LT; - case '>': - return XML.GT; - case '/': - return XML.SLASH; - case '=': - return XML.EQ; - case '!': - return XML.BANG; - case '?': - return XML.QUEST; - case '"': - case '\'': - q = c; - for (;;) { - c = next(); - if (c == 0) { - throw syntaxError("Unterminated string"); + case 0: + throw syntaxError("Misshaped meta tag"); + case '<': + return XML.LT; + case '>': + return XML.GT; + case '/': + return XML.SLASH; + case '=': + return XML.EQ; + case '!': + return XML.BANG; + case '?': + return XML.QUEST; + case '"': + case '\'': + q = c; + for (;;) { + c = next(); + if (c == 0) + throw syntaxError("Unterminated string"); + if (c == q) + return Boolean.TRUE; } - if (c == q) { - return Boolean.TRUE; + default: + for (;;) { + c = next(); + if (Character.isWhitespace(c)) + return Boolean.TRUE; + switch (c) { + case 0: + case '<': + case '>': + case '/': + case '=': + case '!': + case '?': + case '"': + case '\'': + back(); + return Boolean.TRUE; + } } - } - default: - for (;;) { - c = next(); - if (Character.isWhitespace(c)) { - return Boolean.TRUE; - } - switch (c) { - case 0: - case '<': - case '>': - case '/': - case '=': - case '!': - case '?': - case '"': - case '\'': - back(); - return Boolean.TRUE; - } - } } } - /** - * Get the next XML Token. These tokens are found inside of angle - * brackets. It may be one of these characters: / > = ! ? or it - * may be a string wrapped in single quotes or double quotes, or it may be a - * name. + * Get the next XML Token. These tokens are found inside of angle brackets. + * It may be one of these characters: / > = ! ? or it may be a + * string wrapped in single quotes or double quotes, or it may be a name. + * * @return a String or a Character. * @throws JSONException If the XML is not well formed. */ @@ -220,92 +214,89 @@ public Object nextToken() throws JSONException { char c; char q; StringBuilder sb; - do { + do c = next(); - } while (Character.isWhitespace(c)); + while (Character.isWhitespace(c)); switch (c) { - case 0: - throw syntaxError("Misshaped element"); - case '<': - throw syntaxError("Misplaced '<'"); - case '>': - return XML.GT; - case '/': - return XML.SLASH; - case '=': - return XML.EQ; - case '!': - return XML.BANG; - case '?': - return XML.QUEST; + case 0: + throw syntaxError("Misshaped element"); + case '<': + throw syntaxError("Misplaced '<'"); + case '>': + return XML.GT; + case '/': + return XML.SLASH; + case '=': + return XML.EQ; + case '!': + return XML.BANG; + case '?': + return XML.QUEST; // Quoted string - case '"': - case '\'': - q = c; - sb = new StringBuilder(); - for (;;) { - c = next(); - if (c == 0) { - throw syntaxError("Unterminated string"); + case '"': + case '\'': + q = c; + sb = new StringBuilder(); + for (;;) { + c = next(); + if (c == 0) + throw syntaxError("Unterminated string"); + if (c == q) + return sb.toString(); + if (c == '&') + sb.append(nextEntity(c)); + else + sb.append(c); } - if (c == q) { - return sb.toString(); - } - if (c == '&') { - sb.append(nextEntity(c)); - } else { - sb.append(c); - } - } - default: + default: // Name - sb = new StringBuilder(); - for (;;) { - sb.append(c); - c = next(); - if (Character.isWhitespace(c)) { - return sb.toString(); - } - switch (c) { - case 0: - return sb.toString(); - case '>': - case '/': - case '=': - case '!': - case '?': - case '[': - case ']': - back(); - return sb.toString(); - case '<': - case '"': - case '\'': - throw syntaxError("Bad character in a name"); + sb = new StringBuilder(); + for (;;) { + sb.append(c); + c = next(); + if (Character.isWhitespace(c)) + return sb.toString(); + switch (c) { + case 0: + return sb.toString(); + case '>': + case '/': + case '=': + case '!': + case '?': + case '[': + case ']': + back(); + return sb.toString(); + case '<': + case '"': + case '\'': + throw syntaxError("Bad character in a name"); + } } - } } } - /** - * Skip characters until past the requested string. - * If it is not found, we are left at the end of the source with a result of false. + * Skip characters until past the requested string. If it is not found, we + * are left at the end of the source with a result of false. + * * @param to A string to skip past. - * @throws JSONException + * @return True if we did not reach the end + * @throws JSONException If something goes wrong */ - public boolean skipPast(String to) throws JSONException { + public boolean skipPast(final String to) throws JSONException { boolean b; char c; int i; int j; int offset = 0; - int length = to.length(); - char[] circle = new char[length]; + final int length = to.length(); + final char[] circle = new char[length]; /* * First fill the circle buffer with as many characters as are in the @@ -314,9 +305,8 @@ public boolean skipPast(String to) throws JSONException { for (i = 0; i < length; i += 1) { c = next(); - if (c == 0) { + if (c == 0) return false; - } circle[i] = c; } @@ -334,32 +324,28 @@ public boolean skipPast(String to) throws JSONException { break; } j += 1; - if (j >= length) { + if (j >= length) j -= length; - } } /* If we exit the loop with b intact, then victory is ours. */ - if (b) { + if (b) return true; - } /* Get the next character. If there isn't one, then defeat is ours. */ c = next(); - if (c == 0) { + if (c == 0) return false; - } /* * Shove the character in the circle buffer and advance the * circle offset. The offset is mod n. */ circle[offset] = c; offset += 1; - if (offset >= length) { + if (offset >= length) offset -= length; - } } } }