From 48923292e2ba0b5066176bea9968e445c1ddb242 Mon Sep 17 00:00:00 2001 From: Nicholas Cull Date: Tue, 14 Jun 2016 22:38:56 +1000 Subject: [PATCH 01/13] Adapt JSONWriter to use Appendable instead of Writer. Change JSONObject, JSONArray, and JSONStringer to use Appendable where appropriate. This removes the need for synchronization in a few areas. --- JSONArray.java | 39 ++++++------ JSONObject.java | 156 +++++++++++++++++++--------------------------- JSONStringer.java | 4 +- JSONWriter.java | 17 +++-- 4 files changed, 92 insertions(+), 124 deletions(-) mode change 100644 => 100755 JSONArray.java mode change 100644 => 100755 JSONObject.java mode change 100644 => 100755 JSONStringer.java mode change 100644 => 100755 JSONWriter.java diff --git a/JSONArray.java b/JSONArray.java old mode 100644 new mode 100755 index 776a2bd05..c7d01c404 --- a/JSONArray.java +++ b/JSONArray.java @@ -26,7 +26,6 @@ of this software and associated documentation files (the "Software"), to deal import java.io.IOException; import java.io.StringWriter; -import java.io.Writer; import java.lang.reflect.Array; import java.math.BigDecimal; import java.math.BigInteger; @@ -250,7 +249,7 @@ public double getDouble(int index) throws JSONException { /** * Get the enum value associated with an index. - * + * * @param clazz * The type of enum to retrieve. * @param index @@ -559,7 +558,7 @@ public int optInt(int index, int defaultValue) { /** * Get the enum value associated with a key. - * + * * @param clazz * The type of enum to retrieve. * @param index @@ -572,7 +571,7 @@ public > E optEnum(Class clazz, int index) { /** * Get the enum value associated with a key. - * + * * @param clazz * The type of enum to retrieve. * @param index @@ -604,8 +603,8 @@ 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 @@ -623,8 +622,8 @@ public BigInteger optBigInteger(int index, BigInteger 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 @@ -959,9 +958,9 @@ public JSONArray put(int index, Object value) throws JSONException { } return this; } - + /** - * Creates a JSONPointer using an intialization string and tries to + * Creates a JSONPointer using an intialization string and tries to * match it to an item within this JSONArray. For example, given a * JSONArray initialized with this document: *
@@ -969,7 +968,7 @@ public JSONArray put(int index, Object value) throws JSONException {
      *     {"b":"c"}
      * ]
      * 
- * and this JSONPointer string: + * and this JSONPointer string: *
      * "/0/b"
      * 
@@ -982,11 +981,11 @@ public JSONArray put(int index, Object value) throws JSONException { public Object query(String jsonPointer) { return new JSONPointer(jsonPointer).queryFrom(this); } - + /** * Queries and returns a value from this object using {@code jsonPointer}, or * returns null if the query fails due to a missing key. - * + * * @param jsonPointer the string representation of the JSON pointer * @return the queried value or {@code null} * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax @@ -1117,7 +1116,7 @@ public String toString(int indentFactor) throws JSONException { * @return The writer. * @throws JSONException */ - public Writer write(Writer writer) throws JSONException { + public T write(T writer) throws JSONException { return this.write(writer, 0, 0); } @@ -1136,12 +1135,12 @@ public Writer write(Writer writer) throws JSONException { * @return The writer. * @throws JSONException */ - public Writer write(Writer writer, int indentFactor, int indent) + public T write(T writer, int indentFactor, int indent) throws JSONException { try { boolean commanate = false; int length = this.length(); - writer.write('['); + writer.append('['); if (length == 1) { JSONObject.writeValue(writer, this.myArrayList.get(0), @@ -1151,10 +1150,10 @@ public Writer write(Writer writer, int indentFactor, int indent) for (int i = 0; i < length; i += 1) { if (commanate) { - writer.write(','); + writer.append(','); } if (indentFactor > 0) { - writer.write('\n'); + writer.append('\n'); } JSONObject.indent(writer, newindent); JSONObject.writeValue(writer, this.myArrayList.get(i), @@ -1162,11 +1161,11 @@ public Writer write(Writer writer, int indentFactor, int indent) commanate = true; } if (indentFactor > 0) { - writer.write('\n'); + writer.append('\n'); } JSONObject.indent(writer, indent); } - writer.write(']'); + writer.append(']'); return writer; } catch (IOException e) { throw new JSONException(e); diff --git a/JSONObject.java b/JSONObject.java old mode 100644 new mode 100755 index aa227ff09..60956bdd7 --- a/JSONObject.java +++ b/JSONObject.java @@ -26,7 +26,6 @@ of this software and associated documentation files (the "Software"), to deal 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; @@ -475,7 +474,7 @@ public Object get(String key) throws JSONException { /** * Get the enum value associated with a key. - * + * * @param clazz * The type of enum to retrieve. * @param key @@ -530,7 +529,7 @@ public boolean getBoolean(String key) throws JSONException { * A key string. * @return The numeric value. * @throws JSONException - * if the key is not found or if the value cannot + * if the key is not found or if the value cannot * be converted to BigInteger. */ public BigInteger getBigInteger(String key) throws JSONException { @@ -865,7 +864,7 @@ public Object opt(String key) { /** * Get the enum value associated with a key. - * + * * @param clazz * The type of enum to retrieve. * @param key @@ -878,7 +877,7 @@ public > E optEnum(Class clazz, String key) { /** * Get the enum value associated with a key. - * + * * @param clazz * The type of enum to retrieve. * @param key @@ -1339,7 +1338,7 @@ public JSONObject putOpt(String key, Object value) throws JSONException { } /** - * Creates a JSONPointer using an intialization string and tries to + * Creates a JSONPointer using an intialization string and tries to * match it to an item within this JSONObject. For example, given a * JSONObject initialized with this document: *
@@ -1347,24 +1346,24 @@ public JSONObject putOpt(String key, Object value) throws JSONException {
      *     "a":{"b":"c"}
      * }
      * 
- * and this JSONPointer string: + * and this JSONPointer string: *
      * "/a/b"
      * 
* Then this method will return the String "c". * A JSONPointerException may be thrown from code called by this method. - * + * * @param jsonPointer string that can be used to create a JSONPointer * @return the item matched by the JSONPointer, otherwise null */ public Object query(String jsonPointer) { return new JSONPointer(jsonPointer).queryFrom(this); } - + /** * Queries and returns a value from this object using {@code jsonPointer}, or * returns null if the query fails due to a missing key. - * + * * @param jsonPointer the string representation of the JSON pointer * @return the queried value or {@code null} * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax @@ -1388,21 +1387,19 @@ public Object optQuery(String jsonPointer) { * A String * @return A String correctly formatted for insertion in a JSON text. */ - public static String quote(String string) { - StringWriter sw = new StringWriter(); - synchronized (sw.getBuffer()) { - try { - return quote(string, sw).toString(); - } catch (IOException ignored) { - // will never happen - we are writing to a string writer - return ""; - } + public static String quote(CharSequence string) { + StringBuilder sb = new StringBuilder(); + try { + return quote(string, sb).toString(); + } catch (IOException ignored) { + // will never happen - we are writing to a string builder + return ""; } } - public static Writer quote(String string, Writer w) throws IOException { + public static T quote(CharSequence string, T w) throws IOException { if (string == null || string.length() == 0) { - w.write("\"\""); + w.append("\"\""); return w; } @@ -1412,50 +1409,50 @@ public static Writer quote(String string, Writer w) throws IOException { int i; int len = string.length(); - w.write('"'); + w.append('"'); for (i = 0; i < len; i += 1) { b = c; c = string.charAt(i); switch (c) { case '\\': case '"': - w.write('\\'); - w.write(c); + w.append('\\'); + w.append(c); break; case '/': if (b == '<') { - w.write('\\'); + w.append('\\'); } - w.write(c); + w.append(c); break; case '\b': - w.write("\\b"); + w.append("\\b"); break; case '\t': - w.write("\\t"); + w.append("\\t"); break; case '\n': - w.write("\\n"); + w.append("\\n"); break; case '\f': - w.write("\\f"); + w.append("\\f"); break; case '\r': - w.write("\\r"); + w.append("\\r"); break; default: if (c < ' ' || (c >= '\u0080' && c < '\u00a0') || (c >= '\u2000' && c < '\u2100')) { - w.write("\\u"); + w.append("\\u"); hhhh = Integer.toHexString(c); - w.write("0000", 0, 4 - hhhh.length()); - w.write(hhhh); + w.append("0000", 0, 4 - hhhh.length()); + w.append(hhhh); } else { - w.write(c); + w.append(c); } } } - w.write('"'); + w.append('"'); return w; } @@ -1675,40 +1672,11 @@ public String toString(int indentFactor) 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)) { - return "null"; - } - if (value instanceof JSONString) { - Object object; - try { - object = ((JSONString) value).toJSONString(); - } catch (Exception e) { - throw new JSONException(e); - } - 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 Boolean || value instanceof JSONObject - || value instanceof JSONArray) { - return value.toString(); - } - if (value instanceof Map) { - Map map = (Map) value; - return new JSONObject(map).toString(); - } - if (value instanceof Collection) { - Collection coll = (Collection) value; - return new JSONArray(coll).toString(); - } - if (value.getClass().isArray()) { - return new JSONArray(value).toString(); + try { + return writeValue(new StringBuilder(), value, 0, 0).toString(); + } catch (IOException e) { + throw new JSONException(e); } - return quote(value.toString()); } /** @@ -1773,14 +1741,14 @@ public static Object wrap(Object object) { * @return The writer. * @throws JSONException */ - public Writer write(Writer writer) throws JSONException { + public T write(T writer) throws JSONException { return this.write(writer, 0, 0); } - static final Writer writeValue(Writer writer, Object value, + static final T writeValue(T writer, Object value, int indentFactor, int indent) throws JSONException, IOException { if (value == null || value.equals(null)) { - writer.write("null"); + writer.append("null"); } else if (value instanceof JSONObject) { ((JSONObject) value).write(writer, indentFactor, indent); } else if (value instanceof JSONArray) { @@ -1794,26 +1762,30 @@ static final Writer writeValue(Writer writer, Object value, } else if (value.getClass().isArray()) { new JSONArray(value).write(writer, indentFactor, indent); } else if (value instanceof Number) { - writer.write(numberToString((Number) value)); + writer.append(numberToString((Number) value)); } else if (value instanceof Boolean) { - writer.write(value.toString()); + writer.append(value.toString()); } else if (value instanceof JSONString) { - Object o; + String o; try { o = ((JSONString) value).toJSONString(); } catch (Exception e) { throw new JSONException(e); } - writer.write(o != null ? o.toString() : quote(value.toString())); + if (o != null) { + writer.append(o); + } else { + quote(value.toString(), writer); + } } else { quote(value.toString(), writer); } return writer; } - static final void indent(Writer writer, int indent) throws IOException { + static final void indent(T writer, int indent) throws IOException { for (int i = 0; i < indent; i += 1) { - writer.write(' '); + writer.append(' '); } } @@ -1832,47 +1804,47 @@ static final void indent(Writer writer, int indent) throws IOException { * @return The writer. * @throws JSONException */ - public Writer write(Writer writer, int indentFactor, int indent) + public T write(T writer, int indentFactor, int indent) throws JSONException { try { boolean commanate = false; final int length = this.length(); Iterator keys = this.keys(); - writer.write('{'); + writer.append('{'); if (length == 1) { - Object key = keys.next(); - writer.write(quote(key.toString())); - writer.write(':'); + String key = keys.next(); + quote(key, writer); + writer.append(':'); if (indentFactor > 0) { - writer.write(' '); + writer.append(' '); } writeValue(writer, this.map.get(key), indentFactor, indent); } else if (length != 0) { final int newindent = indent + indentFactor; while (keys.hasNext()) { - Object key = keys.next(); + String key = keys.next(); if (commanate) { - writer.write(','); + writer.append(','); } if (indentFactor > 0) { - writer.write('\n'); + writer.append('\n'); } indent(writer, newindent); - writer.write(quote(key.toString())); - writer.write(':'); + quote(key, writer); + writer.append(':'); if (indentFactor > 0) { - writer.write(' '); + writer.append(' '); } writeValue(writer, this.map.get(key), indentFactor, newindent); commanate = true; } if (indentFactor > 0) { - writer.write('\n'); + writer.append('\n'); } indent(writer, indent); } - writer.write('}'); + writer.append('}'); return writer; } catch (IOException exception) { throw new JSONException(exception); diff --git a/JSONStringer.java b/JSONStringer.java old mode 100644 new mode 100755 index 5fbc96a9a..a7289b946 --- a/JSONStringer.java +++ b/JSONStringer.java @@ -24,8 +24,6 @@ of this software and associated documentation files (the "Software"), to deal SOFTWARE. */ -import java.io.StringWriter; - /** * JSONStringer provides a quick and convenient way of producing JSON text. * The texts produced strictly conform to JSON syntax rules. No whitespace is @@ -61,7 +59,7 @@ public class JSONStringer extends JSONWriter { * Make a fresh JSONStringer. It can be used to build one JSON text. */ public JSONStringer() { - super(new StringWriter()); + super(new StringBuilder()); } /** diff --git a/JSONWriter.java b/JSONWriter.java old mode 100644 new mode 100755 index 09d113030..22db7966c --- a/JSONWriter.java +++ b/JSONWriter.java @@ -1,7 +1,6 @@ package org.json; import java.io.IOException; -import java.io.Writer; /* Copyright (c) 2006 JSON.org @@ -88,12 +87,12 @@ public class JSONWriter { /** * The writer that will receive the output. */ - protected Writer writer; + protected Appendable writer; /** * Make a fresh JSONWriter. It can be used to build one JSON text. */ - public JSONWriter(Writer w) { + public JSONWriter(Appendable w) { this.comma = false; this.mode = 'i'; this.stack = new JSONObject[maxdepth]; @@ -114,9 +113,9 @@ private JSONWriter append(String string) throws JSONException { if (this.mode == 'o' || this.mode == 'a') { try { if (this.comma && this.mode == 'a') { - this.writer.write(','); + this.writer.append(','); } - this.writer.write(string); + this.writer.append(string); } catch (IOException e) { throw new JSONException(e); } @@ -163,7 +162,7 @@ private JSONWriter end(char mode, char c) throws JSONException { } this.pop(mode); try { - this.writer.write(c); + this.writer.append(c); } catch (IOException e) { throw new JSONException(e); } @@ -207,10 +206,10 @@ public JSONWriter key(String string) throws JSONException { try { this.stack[this.top - 1].putOnce(string, Boolean.TRUE); if (this.comma) { - this.writer.write(','); + this.writer.append(','); } - this.writer.write(JSONObject.quote(string)); - this.writer.write(':'); + JSONObject.quote(string, this.writer); + this.writer.append(':'); this.comma = false; this.mode = 'o'; return this; From c91c37a0a735ad31374a16dd88ecac73305ae159 Mon Sep 17 00:00:00 2001 From: Nicholas Cull Date: Tue, 14 Jun 2016 22:41:35 +1000 Subject: [PATCH 02/13] Remove executable bit. --- JSONArray.java | 0 JSONObject.java | 0 JSONStringer.java | 0 JSONWriter.java | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 JSONArray.java mode change 100755 => 100644 JSONObject.java mode change 100755 => 100644 JSONStringer.java mode change 100755 => 100644 JSONWriter.java diff --git a/JSONArray.java b/JSONArray.java old mode 100755 new mode 100644 diff --git a/JSONObject.java b/JSONObject.java old mode 100755 new mode 100644 diff --git a/JSONStringer.java b/JSONStringer.java old mode 100755 new mode 100644 diff --git a/JSONWriter.java b/JSONWriter.java old mode 100755 new mode 100644 From 826ceefe4adc718f00c6b03e8b0badc1974941bb Mon Sep 17 00:00:00 2001 From: Nicholas Cull Date: Sat, 2 Jul 2016 13:59:13 +1000 Subject: [PATCH 03/13] Minor tweaks. --- JSONArray.java | 2 +- JSONObject.java | 15 ++++++++++----- JSONWriter.java | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) mode change 100644 => 100755 JSONArray.java mode change 100644 => 100755 JSONObject.java mode change 100644 => 100755 JSONWriter.java diff --git a/JSONArray.java b/JSONArray.java old mode 100644 new mode 100755 index c7d01c404..2047164f0 --- a/JSONArray.java +++ b/JSONArray.java @@ -434,7 +434,7 @@ public String join(String separator) throws JSONException { if (i > 0) { sb.append(separator); } - sb.append(JSONObject.valueToString(this.myArrayList.get(i))); + JSONObject.writeValue(sb, this.myArrayList.get(i)); } return sb.toString(); } diff --git a/JSONObject.java b/JSONObject.java old mode 100644 new mode 100755 index 60956bdd7..d741d802b --- a/JSONObject.java +++ b/JSONObject.java @@ -1672,11 +1672,7 @@ public String toString(int indentFactor) throws JSONException { * If the value is or contains an invalid number. */ public static String valueToString(Object value) throws JSONException { - try { - return writeValue(new StringBuilder(), value, 0, 0).toString(); - } catch (IOException e) { - throw new JSONException(e); - } + return writeValue(new StringBuilder(), value).toString(); } /** @@ -1745,6 +1741,15 @@ public T write(T writer) throws JSONException { return this.write(writer, 0, 0); } + static T writeValue(T writer, Object value) + throws JSONException { + try { + return writeValue(writer, value, 0 ,0); + } catch (IOException e) { + throw new JSONException(e); + } + } + static final T writeValue(T writer, Object value, int indentFactor, int indent) throws JSONException, IOException { if (value == null || value.equals(null)) { diff --git a/JSONWriter.java b/JSONWriter.java old mode 100644 new mode 100755 index 22db7966c..96ab6c498 --- a/JSONWriter.java +++ b/JSONWriter.java @@ -299,7 +299,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 this.append(JSONObject.numberToString(Double.valueOf(d))); } /** From 2917cc54ea9ffa36144f3fb9a6b4b3f380becfab Mon Sep 17 00:00:00 2001 From: Nicholas Cull Date: Sat, 2 Jul 2016 14:00:27 +1000 Subject: [PATCH 04/13] Minor tweaks. --- JSONArray.java | 0 JSONObject.java | 0 JSONWriter.java | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 JSONArray.java mode change 100755 => 100644 JSONObject.java mode change 100755 => 100644 JSONWriter.java diff --git a/JSONArray.java b/JSONArray.java old mode 100755 new mode 100644 diff --git a/JSONObject.java b/JSONObject.java old mode 100755 new mode 100644 diff --git a/JSONWriter.java b/JSONWriter.java old mode 100755 new mode 100644 From 0f579e4958e095b54d90370283610f9cd6195026 Mon Sep 17 00:00:00 2001 From: run2000 Date: Thu, 28 Jul 2016 09:30:30 +1000 Subject: [PATCH 05/13] Update version string --- JSONArray.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONArray.java b/JSONArray.java index 0d98e8937..e9ddb11f6 100755 --- a/JSONArray.java +++ b/JSONArray.java @@ -77,7 +77,7 @@ of this software and associated documentation files (the "Software"), to deal * * * @author JSON.org - * @version 2016-07-19 + * @version 2016-07-28 */ public class JSONArray implements Iterable { From 5daf2b9ba388b6d9921b0fb789c0608413cc0339 Mon Sep 17 00:00:00 2001 From: run2000 Date: Thu, 28 Jul 2016 09:30:59 +1000 Subject: [PATCH 06/13] Update version string --- JSONStringer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONStringer.java b/JSONStringer.java index a7289b946..056913373 100644 --- a/JSONStringer.java +++ b/JSONStringer.java @@ -52,7 +52,7 @@ of this software and associated documentation files (the "Software"), to deal *

* This can sometimes be easier than using a JSONObject to build a string. * @author JSON.org - * @version 2015-12-09 + * @version 2016-07-28 */ public class JSONStringer extends JSONWriter { /** From e94e25b41b1c6b9555f933b2a538470e057d7ffb Mon Sep 17 00:00:00 2001 From: run2000 Date: Thu, 28 Jul 2016 09:31:32 +1000 Subject: [PATCH 07/13] Update version string --- JSONObject.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONObject.java b/JSONObject.java index e72c3c7d0..05d8003af 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -92,7 +92,7 @@ of this software and associated documentation files (the "Software"), to deal * * * @author JSON.org - * @version 2016-07-19 + * @version 2016-07-28 */ public class JSONObject { /** From bec3919688337fa549ef7e40a24ff3b3f92686ea Mon Sep 17 00:00:00 2001 From: run2000 Date: Thu, 28 Jul 2016 09:32:09 +1000 Subject: [PATCH 08/13] Update version string --- JSONWriter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSONWriter.java b/JSONWriter.java index 96ab6c498..448943590 100644 --- a/JSONWriter.java +++ b/JSONWriter.java @@ -53,7 +53,7 @@ of this software and associated documentation files (the "Software"), to deal *

* This can sometimes be easier than using a JSONObject to build a string. * @author JSON.org - * @version 2015-12-09 + * @version 2016-07-28 */ public class JSONWriter { private static final int maxdepth = 200; From 0412cf17cea61c6253f628c8971b407e7d04c84d Mon Sep 17 00:00:00 2001 From: run2000 Date: Thu, 28 Jul 2016 09:50:33 +1000 Subject: [PATCH 09/13] Javadoc and copyright notice for JSONString This goes through the `null` return, and also documents what happens if a runtime exception is thrown. --- JSONString.java | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/JSONString.java b/JSONString.java index 1f2d77dd1..26f8601aa 100644 --- a/JSONString.java +++ b/JSONString.java @@ -1,4 +1,29 @@ package org.json; + +/* +Copyright (c) 2002 JSON.org + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The Software shall be used for Good, not Evil. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + /** * The JSONString interface allows a toJSONString() * method so that a class can change the behavior of @@ -6,13 +31,25 @@ * and JSONWriter.value(Object). The * toJSONString method will be used instead of the default behavior * of using the Object's toString() method and quoting the result. + *

+ * If toJSONString() returns null, the class's + * toString() value will be quoted and used.

+ * + * @author json.org + * @version 2016-07-28 */ public interface JSONString { /** * The toJSONString method allows a class to produce its own JSON - * serialization. + * serialization. If null is returned, the class's + * toString method will be called, and the result will be + * quoted and used. + *

+ * If a runtime exception is thrown, this will be caught and propagated + * as a JSONException.

* - * @return A strictly syntactically correct JSON text. + * @return A strictly syntactically correct JSON text, or null + * to indicate the toString value should be used instead */ public String toJSONString(); } From 288c9883f2846785b515d583d963480abddbb4b1 Mon Sep 17 00:00:00 2001 From: Nicholas Cull Date: Thu, 28 Jul 2016 22:36:58 +1000 Subject: [PATCH 10/13] Cygwin fails me again, remove the execute bit. --- JSONArray.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 JSONArray.java diff --git a/JSONArray.java b/JSONArray.java old mode 100755 new mode 100644 From c8c95c95c694715373c3ef0f7f5aee18c47736cc Mon Sep 17 00:00:00 2001 From: Nicholas Cull Date: Thu, 4 Aug 2016 23:17:10 +1000 Subject: [PATCH 11/13] Revert whitespace, direct JSONObject.writeValue() call. Fix up whitespace that was causing headaches for review. JSONWriter.value(Object) calls JSONObject.writeValue(Appendable, Object) directly, instead of going through the intermediary of valueToString(). This means it writes to the given Appendable directly, rather than builing a String value using a buffer, then writing the buffer. --- JSONArray.java | 31 +++++++++++++---------------- JSONObject.java | 52 +++++++++++++++++++++++++++++++++++++------------ JSONWriter.java | 19 ++++++++++++++++-- 3 files changed, 71 insertions(+), 31 deletions(-) diff --git a/JSONArray.java b/JSONArray.java index e9ddb11f6..4b22e4218 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -25,7 +25,6 @@ of this software and associated documentation files (the "Software"), to deal */ import java.io.IOException; -import java.io.StringWriter; import java.lang.reflect.Array; import java.math.BigDecimal; import java.math.BigInteger; @@ -77,7 +76,7 @@ of this software and associated documentation files (the "Software"), to deal * * * @author JSON.org - * @version 2016-07-28 + * @version 2016-08-04 */ public class JSONArray implements Iterable { @@ -253,7 +252,7 @@ public double getDouble(int index) throws JSONException { /** * Get the enum value associated with an index. - * + * * @param clazz * The type of enum to retrieve. * @param index @@ -597,7 +596,7 @@ public int optInt(int index, int defaultValue) { /** * Get the enum value associated with a key. - * + * * @param clazz * The type of enum to retrieve. * @param index @@ -610,7 +609,7 @@ public > E optEnum(Class clazz, int index) { /** * Get the enum value associated with a key. - * + * * @param clazz * The type of enum to retrieve. * @param index @@ -642,8 +641,8 @@ 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 @@ -665,8 +664,8 @@ public BigInteger optBigInteger(int index, BigInteger 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 @@ -1016,7 +1015,7 @@ public JSONArray put(int index, Object value) throws JSONException { } /** - * Creates a JSONPointer using an initialization string and tries to + * Creates a JSONPointer using an initialization string and tries to * match it to an item within this JSONArray. For example, given a * JSONArray initialized with this document: *
@@ -1024,13 +1023,13 @@ public JSONArray put(int index, Object value) throws JSONException {
      *     {"b":"c"}
      * ]
      * 
- * and this JSONPointer string: + * and this JSONPointer string: *
      * "/0/b"
      * 
* Then this method will return the String "c" * A JSONPointerException may be thrown from code called by this method. - * + * * @param jsonPointer string that can be used to create a JSONPointer * @return the item matched by the JSONPointer, otherwise null */ @@ -1041,7 +1040,7 @@ public Object query(String jsonPointer) { /** * Queries and returns a value from this object using {@code jsonPointer}, or * returns null if the query fails due to a missing key. - * + * * @param jsonPointer the string representation of the JSON pointer * @return the queried value or {@code null} * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax @@ -1158,10 +1157,8 @@ public String toString() { * @throws JSONException */ public String toString(int indentFactor) throws JSONException { - StringWriter sw = new StringWriter(); - synchronized (sw.getBuffer()) { - return this.write(sw, indentFactor, 0).toString(); - } + StringBuilder sw = new StringBuilder(); + return this.write(sw, indentFactor, 0).toString(); } /** diff --git a/JSONObject.java b/JSONObject.java index 05d8003af..bd8d0d5d5 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -25,7 +25,6 @@ of this software and associated documentation files (the "Software"), to deal */ import java.io.IOException; -import java.io.StringWriter; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -92,7 +91,7 @@ of this software and associated documentation files (the "Software"), to deal * * * @author JSON.org - * @version 2016-07-28 + * @version 2016-08-04 */ public class JSONObject { /** @@ -1462,6 +1461,7 @@ public static T quote(CharSequence string, T w) throws IO String hhhh; int i; int len = string.length(); + int prev = 0; w.append('"'); for (i = 0; i < len; i += 1) { @@ -1470,42 +1470,72 @@ public static T quote(CharSequence string, T w) throws IO switch (c) { case '\\': case '"': + if(prev < i) { + w.append(string, prev, i); + } w.append('\\'); - w.append(c); + prev = i; break; case '/': if (b == '<') { + if(prev < i) { + w.append(string, prev, i); + } w.append('\\'); + prev = i; } - w.append(c); break; case '\b': + if(prev < i) { + w.append(string, prev, i); + } w.append("\\b"); + prev = i + 1; break; case '\t': + if(prev < i) { + w.append(string, prev, i); + } w.append("\\t"); + prev = i + 1; break; case '\n': + if(prev < i) { + w.append(string, prev, i); + } w.append("\\n"); + prev = i + 1; break; case '\f': + if(prev < i) { + w.append(string, prev, i); + } w.append("\\f"); + prev = i + 1; break; case '\r': + if(prev < i) { + w.append(string, prev, i); + } w.append("\\r"); + prev = i + 1; break; default: if (c < ' ' || (c >= '\u0080' && c < '\u00a0') || (c >= '\u2000' && c < '\u2100')) { - w.append("\\u"); + if(prev < i) { + w.append(string, prev, i); + } hhhh = Integer.toHexString(c); - w.append("0000", 0, 4 - hhhh.length()); + w.append("\\u0000", 0, 6 - hhhh.length()); w.append(hhhh); - } else { - w.append(c); + prev = i + 1; } } } + if(prev < i) { + w.append(string, prev, i); + } w.append('"'); return w; } @@ -1696,10 +1726,8 @@ public String toString() { * If the object contains an invalid number. */ public String toString(int indentFactor) throws JSONException { - StringWriter w = new StringWriter(); - synchronized (w.getBuffer()) { - return this.write(w, indentFactor, 0).toString(); - } + StringBuilder w = new StringBuilder(); + return this.write(w, indentFactor, 0).toString(); } /** diff --git a/JSONWriter.java b/JSONWriter.java index 448943590..9915a09e5 100644 --- a/JSONWriter.java +++ b/JSONWriter.java @@ -53,7 +53,7 @@ of this software and associated documentation files (the "Software"), to deal *

* This can sometimes be easier than using a JSONObject to build a string. * @author JSON.org - * @version 2016-07-28 + * @version 2016-08-04 */ public class JSONWriter { private static final int maxdepth = 200; @@ -321,6 +321,21 @@ 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)); + if (this.mode == 'o' || this.mode == 'a') { + try { + if (this.comma && this.mode == 'a') { + this.writer.append(','); + } + JSONObject.writeValue(this.writer, object); + } catch (IOException e) { + throw new JSONException(e); + } + if (this.mode == 'o') { + this.mode = 'k'; + } + this.comma = true; + return this; + } + throw new JSONException("Value out of sequence."); } } From 70f0dd97bca65c19d3aac97b2f70e39233c399c7 Mon Sep 17 00:00:00 2001 From: Nicholas Cull Date: Fri, 5 Aug 2016 20:25:33 +1000 Subject: [PATCH 12/13] Use appendValue, based on append, for writing directly. --- JSONObject.java | 6 ++++-- JSONWriter.java | 50 +++++++++++++++++++++++++++++++------------------ 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/JSONObject.java b/JSONObject.java index bd8d0d5d5..f2da8fcd3 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -1533,8 +1533,10 @@ public static T quote(CharSequence string, T w) throws IO } } } - if(prev < i) { - w.append(string, prev, i); + if(prev == 0) { + w.append(string); + } else if(prev < len) { + w.append(string, prev, len); } w.append('"'); return w; diff --git a/JSONWriter.java b/JSONWriter.java index 9915a09e5..ea5b06fd4 100644 --- a/JSONWriter.java +++ b/JSONWriter.java @@ -49,7 +49,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 @@ -101,7 +101,7 @@ public JSONWriter(Appendable w) { } /** - * Append a value. + * Append a JSON-encoded value. * @param string A string value. * @return this * @throws JSONException If the value is out of sequence. @@ -128,6 +128,35 @@ private JSONWriter append(String string) throws JSONException { throw new JSONException("Value out of sequence."); } + /** + * Append a value, converting it into a JSON string. + * + * @param val A value. + * @return this + * @throws JSONException If the value is out of sequence. + */ + private JSONWriter appendValue(Object val) throws JSONException { + try { + switch (this.mode) { + case 'a': + if (this.comma) { + this.writer.append(','); + } + break; + case 'o': + this.mode = 'k'; + break; + default: + throw new JSONException("Value out of sequence."); + } + JSONObject.writeValue(this.writer, val); + this.comma = true; + return this; + } catch (IOException e) { + throw new JSONException(e); + } + } + /** * Begin appending a new array. All values until the balancing * endArray will be appended to this array. The @@ -321,21 +350,6 @@ public JSONWriter value(long l) throws JSONException { * @throws JSONException If the value is out of sequence. */ public JSONWriter value(Object object) throws JSONException { - if (this.mode == 'o' || this.mode == 'a') { - try { - if (this.comma && this.mode == 'a') { - this.writer.append(','); - } - JSONObject.writeValue(this.writer, object); - } catch (IOException e) { - throw new JSONException(e); - } - if (this.mode == 'o') { - this.mode = 'k'; - } - this.comma = true; - return this; - } - throw new JSONException("Value out of sequence."); + return this.appendValue(object); } } From 73c515584af162a9b5dff3e1c5c1854373359750 Mon Sep 17 00:00:00 2001 From: Nicholas Cull Date: Fri, 5 Aug 2016 20:37:03 +1000 Subject: [PATCH 13/13] Revert whitespace. --- JSONArray.java | 6 +++--- JSONObject.java | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/JSONArray.java b/JSONArray.java index 4b22e4218..c876f42a9 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -1013,7 +1013,7 @@ public JSONArray put(int index, Object value) throws JSONException { } return this; } - + /** * Creates a JSONPointer using an initialization string and tries to * match it to an item within this JSONArray. For example, given a @@ -1029,14 +1029,14 @@ public JSONArray put(int index, Object value) throws JSONException { * * Then this method will return the String "c" * A JSONPointerException may be thrown from code called by this method. - * + * * @param jsonPointer string that can be used to create a JSONPointer * @return the item matched by the JSONPointer, otherwise null */ public Object query(String jsonPointer) { return new JSONPointer(jsonPointer).queryFrom(this); } - + /** * Queries and returns a value from this object using {@code jsonPointer}, or * returns null if the query fails due to a missing key. diff --git a/JSONObject.java b/JSONObject.java index f2da8fcd3..20cdaa270 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -474,7 +474,7 @@ public Object get(String key) throws JSONException { /** * Get the enum value associated with a key. - * + * * @param clazz * The type of enum to retrieve. * @param key @@ -529,7 +529,7 @@ public boolean getBoolean(String key) throws JSONException { * A key string. * @return The numeric value. * @throws JSONException - * if the key is not found or if the value cannot + * if the key is not found or if the value cannot * be converted to BigInteger. */ public BigInteger getBigInteger(String key) throws JSONException { @@ -873,7 +873,7 @@ public Object opt(String key) { /** * Get the enum value associated with a key. - * + * * @param clazz * The type of enum to retrieve. * @param key @@ -886,7 +886,7 @@ public > E optEnum(Class clazz, String key) { /** * Get the enum value associated with a key. - * + * * @param clazz * The type of enum to retrieve. * @param key @@ -1391,7 +1391,7 @@ public JSONObject putOpt(String key, Object value) throws JSONException { } /** - * Creates a JSONPointer using an intialization string and tries to + * Creates a JSONPointer using an intialization string and tries to * match it to an item within this JSONObject. For example, given a * JSONObject initialized with this document: *

@@ -1399,24 +1399,24 @@ public JSONObject putOpt(String key, Object value) throws JSONException {
      *     "a":{"b":"c"}
      * }
      * 
- * and this JSONPointer string: + * and this JSONPointer string: *
      * "/a/b"
      * 
* Then this method will return the String "c". * A JSONPointerException may be thrown from code called by this method. - * + * * @param jsonPointer string that can be used to create a JSONPointer * @return the item matched by the JSONPointer, otherwise null */ public Object query(String jsonPointer) { return new JSONPointer(jsonPointer).queryFrom(this); } - + /** * Queries and returns a value from this object using {@code jsonPointer}, or * returns null if the query fails due to a missing key. - * + * * @param jsonPointer the string representation of the JSON pointer * @return the queried value or {@code null} * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax