From 88f27f316811a3a6a47cca6e98e7255fc93529a2 Mon Sep 17 00:00:00 2001 From: Douglas Crockford Date: Sun, 16 Oct 2011 10:24:08 -0700 Subject: [PATCH] non-number numbers --- JSONObject.java | 94 ++++++++++++++++++++++++++----------------------- Test.java | 10 +++++- 2 files changed, 58 insertions(+), 46 deletions(-) diff --git a/JSONObject.java b/JSONObject.java index a2b3edf..5f3ceec 100755 --- a/JSONObject.java +++ b/JSONObject.java @@ -61,7 +61,7 @@ import java.util.ResourceBundle; * 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();
* produces the string {"JSON": "Hello, World"}. *

@@ -86,7 +86,7 @@ import java.util.ResourceBundle; *

  • Numbers may have the 0x- (hex) prefix.
  • * * @author JSON.org - * @version 2011-04-05 + * @version 2011-10-16 */ public class JSONObject { @@ -155,7 +155,7 @@ public class JSONObject { * Missing keys are ignored. * @param jo A JSONObject. * @param names An array of strings. - * @throws JSONException + * @throws JSONException * @exception JSONException If a value is a non-finite number or if a name is duplicated. */ public JSONObject(JSONObject jo, String[] names) { @@ -231,7 +231,7 @@ public class JSONObject { * * @param map A map object that can be used to initialize the contents of * the JSONObject. - * @throws JSONException + * @throws JSONException */ public JSONObject(Map map) { this.map = new HashMap(); @@ -319,20 +319,20 @@ public class JSONObject { */ public JSONObject(String baseName, Locale locale) throws JSONException { this(); - ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, + ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, Thread.currentThread().getContextClassLoader()); // Iterate through the keys in the bundle. - + Enumeration keys = bundle.getKeys(); while (keys.hasMoreElements()) { Object key = keys.nextElement(); if (key instanceof String) { - -// Go through the path, ensuring that there is a nested JSONObject for each + +// 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; JSONObject target = this; @@ -350,16 +350,16 @@ public class JSONObject { } } - + /** * Accumulate values under a key. It is similar to the put method except * 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. - * + * * 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 + * 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. @@ -368,7 +368,7 @@ public class JSONObject { * or if the key is null. */ public JSONObject accumulate( - String key, + String key, Object value ) throws JSONException { testValidity(value); @@ -425,8 +425,8 @@ public class JSONObject { // 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) { + if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && + string.indexOf('E') < 0) { while (string.endsWith("0")) { string = string.substring(0, string.length() - 1); } @@ -503,7 +503,7 @@ public class JSONObject { /** - * Get the int value associated with a key. + * Get the int value associated with a key. * * @param key A key string. * @return The integer value. @@ -560,7 +560,7 @@ public class JSONObject { /** - * Get the long value associated with a key. + * Get the long value associated with a key. * * @param key A key string. * @return The long value. @@ -649,8 +649,8 @@ public class JSONObject { public boolean has(String key) { return this.map.containsKey(key); } - - + + /** * Increment a property of a JSONObject. If there is no such property, * create one with a value of 1. If there is such a property, and if @@ -667,11 +667,11 @@ public class JSONObject { } else if (value instanceof Integer) { put(key, ((Integer)value).intValue() + 1); } else if (value instanceof Long) { - put(key, ((Long)value).longValue() + 1); + put(key, ((Long)value).longValue() + 1); } else if (value instanceof Double) { - put(key, ((Double)value).doubleValue() + 1); + put(key, ((Double)value).doubleValue() + 1); } else if (value instanceof Float) { - put(key, ((Float)value).floatValue() + 1); + put(key, ((Float)value).floatValue() + 1); } else { throw new JSONException("Unable to increment [" + quote(key) + "]."); } @@ -742,8 +742,8 @@ public class JSONObject { // 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) { + if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && + string.indexOf('E') < 0) { while (string.endsWith("0")) { string = string.substring(0, string.length() - 1); } @@ -946,14 +946,14 @@ public class JSONObject { */ public String optString(String key, String defaultValue) { Object object = opt(key); - return NULL.equals(object) ? defaultValue : object.toString(); + return NULL.equals(object) ? defaultValue : object.toString(); } private void populateMap(Object bean) { Class klass = bean.getClass(); -// If klass is a System class then set includeSuperClass to false. +// If klass is a System class then set includeSuperClass to false. boolean includeSuperClass = klass.getClassLoader() != null; @@ -966,7 +966,7 @@ public class JSONObject { String name = method.getName(); String key = ""; if (name.startsWith("get")) { - if (name.equals("getClass") || + if (name.equals("getClass") || name.equals("getDeclaringClass")) { key = ""; } else { @@ -1147,7 +1147,7 @@ public class JSONObject { /** * Produce a string in double quotes with backslash sequences in all the * right places. A backslash will be inserted within -1 || + if (string.indexOf('.') > -1 || string.indexOf('e') > -1 || string.indexOf('E') > -1) { - return Double.valueOf(string); + d = Double.valueOf(string); + if (!d.isInfinite() && !d.isNaN()) { + return d; + } } else { Long myLong = new Long(string); if (myLong.longValue() == myLong.intValue()) { @@ -1497,8 +1501,8 @@ public class JSONObject { * @throws JSONException If the object contains an invalid number. */ static String valueToString( - Object value, - int indentFactor, + Object value, + int indentFactor, int indent ) throws JSONException { if (value == null || value.equals(null)) { @@ -1539,11 +1543,11 @@ public class JSONObject { /** - * Wrap an object, if necessary. If the object is null, return the NULL - * object. If it is an array or collection, wrap it in a JSONArray. If - * it is a map, wrap it in a JSONObject. If it is a standard property - * (Double, String, et al) then it is already wrapped. Otherwise, if it - * comes from one of the java packages, turn it into a string. And if + * Wrap an object, if necessary. If the object is null, return the NULL + * object. If it is an array or collection, wrap it in a JSONArray. If + * it is a map, wrap it in a JSONObject. If it is a standard property + * (Double, String, et al) then it is already wrapped. Otherwise, if it + * comes from 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. * @@ -1555,16 +1559,16 @@ public class JSONObject { if (object == null) { return NULL; } - if (object instanceof JSONObject || object instanceof JSONArray || - NULL.equals(object) || object instanceof JSONString || + 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 Long || object instanceof Boolean || object instanceof Float || object instanceof Double || object instanceof String) { return object; } - + if (object instanceof Collection) { return new JSONArray((Collection)object); } @@ -1575,7 +1579,7 @@ public class JSONObject { return new JSONObject((Map)object); } Package objectPackage = object.getClass().getPackage(); - String objectPackageName = objectPackage != null ? + String objectPackageName = objectPackage != null ? objectPackage.getName() : ""; if ( objectPackageName.startsWith("java.") || @@ -1590,7 +1594,7 @@ public class JSONObject { } } - + /** * Write the contents of the JSONObject as JSON text to a writer. * For compactness, no whitespace is added. diff --git a/Test.java b/Test.java index bc61e6a..311ac10 100755 --- a/Test.java +++ b/Test.java @@ -40,7 +40,7 @@ SOFTWARE. * comparisons of .toString to a string literal are likely to fail. * * @author JSON.org - * @version 2011-10-05 + * @version 2011-10-16 */ public class Test extends TestCase { public Test(String name) { @@ -67,6 +67,10 @@ public class Test extends TestCase { jsonobject = XML.toJSONObject(string); assertEquals("{\"test\": {\n \"blank\": \"\",\n \"empty\": \"\"\n}}", jsonobject.toString(2)); assertEquals("", XML.toString(jsonobject)); + + string = ""; + jsonobject = XML.toJSONObject(string); + assertEquals("{\"subsonic-response\":\"playlists\":{\"playlist\":[{\"id\":\"476c65652e6d337\"},\"id\":\"50617274792e78737066\"}]}}}", jsonobject.toString()); } public void testNull() throws Exception { @@ -95,6 +99,10 @@ public class Test extends TestCase { jsonarray = new JSONArray(string); assertEquals("[1122334455]", jsonarray.toString()); + string = "[666e666]"; + jsonarray = new JSONArray(string); + assertEquals("[\"666e666\"]", jsonarray.toString()); + string = "[00.10]"; jsonarray = new JSONArray(string); assertEquals("[0.1]", jsonarray.toString());