1
0
Fork 0
mirror of https://github.com/ethauvin/JSON-java.git synced 2025-06-17 07:50:52 -07:00

non-number numbers

This commit is contained in:
Douglas Crockford 2011-10-16 10:24:08 -07:00
parent 3e3951f125
commit 88f27f3168
2 changed files with 58 additions and 46 deletions

View file

@ -61,7 +61,7 @@ import java.util.ResourceBundle;
* coercion for you. The opt methods differ from the get methods in that they * 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. * do not throw. Instead, they return a specified value, such as null.
* <p> * <p>
* The <code>put</code> methods add or replace values in an object. For example, * The <code>put</code> methods add or replace values in an object. For example,
* <pre>myString = new JSONObject().put("JSON", "Hello, World!").toString();</pre> * <pre>myString = new JSONObject().put("JSON", "Hello, World!").toString();</pre>
* produces the string <code>{"JSON": "Hello, World"}</code>. * produces the string <code>{"JSON": "Hello, World"}</code>.
* <p> * <p>
@ -86,7 +86,7 @@ import java.util.ResourceBundle;
* <li>Numbers may have the <code>0x-</code> <small>(hex)</small> prefix.</li> * <li>Numbers may have the <code>0x-</code> <small>(hex)</small> prefix.</li>
* </ul> * </ul>
* @author JSON.org * @author JSON.org
* @version 2011-04-05 * @version 2011-10-16
*/ */
public class JSONObject { public class JSONObject {
@ -155,7 +155,7 @@ public class JSONObject {
* Missing keys are ignored. * Missing keys are ignored.
* @param jo A JSONObject. * @param jo A JSONObject.
* @param names An array of strings. * @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. * @exception JSONException If a value is a non-finite number or if a name is duplicated.
*/ */
public JSONObject(JSONObject jo, String[] names) { 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 * @param map A map object that can be used to initialize the contents of
* the JSONObject. * the JSONObject.
* @throws JSONException * @throws JSONException
*/ */
public JSONObject(Map map) { public JSONObject(Map map) {
this.map = new HashMap(); this.map = new HashMap();
@ -319,20 +319,20 @@ public class JSONObject {
*/ */
public JSONObject(String baseName, Locale locale) throws JSONException { public JSONObject(String baseName, Locale locale) throws JSONException {
this(); this();
ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale,
Thread.currentThread().getContextClassLoader()); Thread.currentThread().getContextClassLoader());
// Iterate through the keys in the bundle. // Iterate through the keys in the bundle.
Enumeration keys = bundle.getKeys(); Enumeration keys = bundle.getKeys();
while (keys.hasMoreElements()) { while (keys.hasMoreElements()) {
Object key = keys.nextElement(); Object key = keys.nextElement();
if (key instanceof String) { 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 // segment except the last. Add the value using the last segment's name into
// the deepest nested JSONObject. // the deepest nested JSONObject.
String[] path = ((String)key).split("\\."); String[] path = ((String)key).split("\\.");
int last = path.length - 1; int last = path.length - 1;
JSONObject target = this; JSONObject target = this;
@ -350,16 +350,16 @@ public class JSONObject {
} }
} }
/** /**
* Accumulate values under a key. It is similar to the put method except * 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 * 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. * 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. * If there is already a JSONArray, then the new value is appended to it.
* In contrast, the put method replaces the previous value. * In contrast, the put method replaces the previous value.
* *
* If only one value is accumulated that is not a JSONArray, then the * 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. * accumulated, then the result will be like append.
* @param key A key string. * @param key A key string.
* @param value An object to be accumulated under the key. * @param value An object to be accumulated under the key.
@ -368,7 +368,7 @@ public class JSONObject {
* or if the key is null. * or if the key is null.
*/ */
public JSONObject accumulate( public JSONObject accumulate(
String key, String key,
Object value Object value
) throws JSONException { ) throws JSONException {
testValidity(value); testValidity(value);
@ -425,8 +425,8 @@ public class JSONObject {
// Shave off trailing zeros and decimal point, if possible. // Shave off trailing zeros and decimal point, if possible.
String string = Double.toString(d); String string = Double.toString(d);
if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && if (string.indexOf('.') > 0 && string.indexOf('e') < 0 &&
string.indexOf('E') < 0) { string.indexOf('E') < 0) {
while (string.endsWith("0")) { while (string.endsWith("0")) {
string = string.substring(0, string.length() - 1); 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. * @param key A key string.
* @return The integer value. * @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. * @param key A key string.
* @return The long value. * @return The long value.
@ -649,8 +649,8 @@ public class JSONObject {
public boolean has(String key) { public boolean has(String key) {
return this.map.containsKey(key); return this.map.containsKey(key);
} }
/** /**
* Increment a property of a JSONObject. If there is no such property, * 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 * 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) { } else if (value instanceof Integer) {
put(key, ((Integer)value).intValue() + 1); put(key, ((Integer)value).intValue() + 1);
} else if (value instanceof Long) { } else if (value instanceof Long) {
put(key, ((Long)value).longValue() + 1); put(key, ((Long)value).longValue() + 1);
} else if (value instanceof Double) { } else if (value instanceof Double) {
put(key, ((Double)value).doubleValue() + 1); put(key, ((Double)value).doubleValue() + 1);
} else if (value instanceof Float) { } else if (value instanceof Float) {
put(key, ((Float)value).floatValue() + 1); put(key, ((Float)value).floatValue() + 1);
} else { } else {
throw new JSONException("Unable to increment [" + quote(key) + "]."); throw new JSONException("Unable to increment [" + quote(key) + "].");
} }
@ -742,8 +742,8 @@ public class JSONObject {
// Shave off trailing zeros and decimal point, if possible. // Shave off trailing zeros and decimal point, if possible.
String string = number.toString(); String string = number.toString();
if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && if (string.indexOf('.') > 0 && string.indexOf('e') < 0 &&
string.indexOf('E') < 0) { string.indexOf('E') < 0) {
while (string.endsWith("0")) { while (string.endsWith("0")) {
string = string.substring(0, string.length() - 1); string = string.substring(0, string.length() - 1);
} }
@ -946,14 +946,14 @@ public class JSONObject {
*/ */
public String optString(String key, String defaultValue) { public String optString(String key, String defaultValue) {
Object object = opt(key); Object object = opt(key);
return NULL.equals(object) ? defaultValue : object.toString(); return NULL.equals(object) ? defaultValue : object.toString();
} }
private void populateMap(Object bean) { private void populateMap(Object bean) {
Class klass = bean.getClass(); 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; boolean includeSuperClass = klass.getClassLoader() != null;
@ -966,7 +966,7 @@ public class JSONObject {
String name = method.getName(); String name = method.getName();
String key = ""; String key = "";
if (name.startsWith("get")) { if (name.startsWith("get")) {
if (name.equals("getClass") || if (name.equals("getClass") ||
name.equals("getDeclaringClass")) { name.equals("getDeclaringClass")) {
key = ""; key = "";
} else { } else {
@ -1147,7 +1147,7 @@ public class JSONObject {
/** /**
* Produce a string in double quotes with backslash sequences in all the * Produce a string in double quotes with backslash sequences in all the
* right places. A backslash will be inserted within </, producing <\/, * right places. A backslash will be inserted within </, producing <\/,
* allowing JSON text to be delivered in HTML. In JSON text, a string * allowing JSON text to be delivered in HTML. In JSON text, a string
* cannot contain a control character or an unescaped quote or backslash. * 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. * @return A String correctly formatted for insertion in a JSON text.
@ -1226,6 +1226,7 @@ public class JSONObject {
* @return A simple JSON value. * @return A simple JSON value.
*/ */
public static Object stringToValue(String string) { public static Object stringToValue(String string) {
Double d;
if (string.equals("")) { if (string.equals("")) {
return string; return string;
} }
@ -1240,8 +1241,8 @@ public class JSONObject {
} }
/* /*
* If it might be a number, try converting it. * If it might be a number, try converting it.
* We support the non-standard 0x- convention. * We support the non-standard 0x- convention.
* If a number cannot be produced, then the value will just * If a number cannot be produced, then the value will just
* be a string. Note that the 0x-, plus, and implied string * be a string. Note that the 0x-, plus, and implied string
* conventions are non-standard. A JSON parser may accept * conventions are non-standard. A JSON parser may accept
@ -1258,9 +1259,12 @@ public class JSONObject {
} }
} }
try { try {
if (string.indexOf('.') > -1 || if (string.indexOf('.') > -1 ||
string.indexOf('e') > -1 || string.indexOf('E') > -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 { } else {
Long myLong = new Long(string); Long myLong = new Long(string);
if (myLong.longValue() == myLong.intValue()) { if (myLong.longValue() == myLong.intValue()) {
@ -1497,8 +1501,8 @@ public class JSONObject {
* @throws JSONException If the object contains an invalid number. * @throws JSONException If the object contains an invalid number.
*/ */
static String valueToString( static String valueToString(
Object value, Object value,
int indentFactor, int indentFactor,
int indent int indent
) throws JSONException { ) throws JSONException {
if (value == null || value.equals(null)) { 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 * 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 * 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 * 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 * (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 * 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, * it doesn't, try to wrap it in a JSONObject. If the wrapping fails,
* then null is returned. * then null is returned.
* *
@ -1555,16 +1559,16 @@ public class JSONObject {
if (object == null) { if (object == null) {
return NULL; return NULL;
} }
if (object instanceof JSONObject || object instanceof JSONArray || if (object instanceof JSONObject || object instanceof JSONArray ||
NULL.equals(object) || object instanceof JSONString || NULL.equals(object) || object instanceof JSONString ||
object instanceof Byte || object instanceof Character || object instanceof Byte || object instanceof Character ||
object instanceof Short || object instanceof Integer || 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 Float || object instanceof Double ||
object instanceof String) { object instanceof String) {
return object; return object;
} }
if (object instanceof Collection) { if (object instanceof Collection) {
return new JSONArray((Collection)object); return new JSONArray((Collection)object);
} }
@ -1575,7 +1579,7 @@ public class JSONObject {
return new JSONObject((Map)object); return new JSONObject((Map)object);
} }
Package objectPackage = object.getClass().getPackage(); Package objectPackage = object.getClass().getPackage();
String objectPackageName = objectPackage != null ? String objectPackageName = objectPackage != null ?
objectPackage.getName() : ""; objectPackage.getName() : "";
if ( if (
objectPackageName.startsWith("java.") || objectPackageName.startsWith("java.") ||
@ -1590,7 +1594,7 @@ public class JSONObject {
} }
} }
/** /**
* Write the contents of the JSONObject as JSON text to a writer. * Write the contents of the JSONObject as JSON text to a writer.
* For compactness, no whitespace is added. * For compactness, no whitespace is added.

View file

@ -40,7 +40,7 @@ SOFTWARE.
* comparisons of .toString to a string literal are likely to fail. * comparisons of .toString to a string literal are likely to fail.
* *
* @author JSON.org * @author JSON.org
* @version 2011-10-05 * @version 2011-10-16
*/ */
public class Test extends TestCase { public class Test extends TestCase {
public Test(String name) { public Test(String name) {
@ -67,6 +67,10 @@ public class Test extends TestCase {
jsonobject = XML.toJSONObject(string); jsonobject = XML.toJSONObject(string);
assertEquals("{\"test\": {\n \"blank\": \"\",\n \"empty\": \"\"\n}}", jsonobject.toString(2)); assertEquals("{\"test\": {\n \"blank\": \"\",\n \"empty\": \"\"\n}}", jsonobject.toString(2));
assertEquals("<test><blank/><empty/></test>", XML.toString(jsonobject)); assertEquals("<test><blank/><empty/></test>", XML.toString(jsonobject));
string = "<subsonic-response><playlists><playlist id=\"476c65652e6d3375\"/><playlist id=\"50617274792e78737066\"/></playlists></subsonic-response>";
jsonobject = XML.toJSONObject(string);
assertEquals("{\"subsonic-response\":\"playlists\":{\"playlist\":[{\"id\":\"476c65652e6d337\"},\"id\":\"50617274792e78737066\"}]}}}", jsonobject.toString());
} }
public void testNull() throws Exception { public void testNull() throws Exception {
@ -95,6 +99,10 @@ public class Test extends TestCase {
jsonarray = new JSONArray(string); jsonarray = new JSONArray(string);
assertEquals("[1122334455]", jsonarray.toString()); assertEquals("[1122334455]", jsonarray.toString());
string = "[666e666]";
jsonarray = new JSONArray(string);
assertEquals("[\"666e666\"]", jsonarray.toString());
string = "[00.10]"; string = "[00.10]";
jsonarray = new JSONArray(string); jsonarray = new JSONArray(string);
assertEquals("[0.1]", jsonarray.toString()); assertEquals("[0.1]", jsonarray.toString());