/* * Copyright 2007 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.json.client; import com.google.gwt.core.client.JsonUtils; import com.google.gwt.junit.client.GWTTestCase; import java.util.Set; /** * Test case for JSONValue and friends. */ public class JSONTest extends GWTTestCase { static final String menuTest = "{\"menu\": {\n" + " \"id\": \"file\",\n" + " \"value\": \"File:\",\n" + " \"popup\": {\n" + " \"menuitem\": [\n" + " {\"value\": \"New\", \"onclick\": \"CreateNewDoc()\"},\n" + " {\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},\n" + " {\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}\n" + " ]\n" + " }\n" + "}}\n" + ""; static final String widgetTest = "{\"widget\": {\n" + " \"debug\": \"on\",\n" + " \"window\": {\n" + " \"title\": \"Sample Konfabulator Widget\", \"name\": \"main_window\", \"width\": 500, \"height\": 500\n" + " }, \"image\": { \n" + " \"src\": \"Images/Sun.png\",\n" + " \"name\": \"sun1\", \"hOffset\": 250, \"vOffset\": 250, \"alignment\": \"center\"\n" + " }, \"text\": {\n" + " \"data\": \"Click Here\",\n" + " \"size\": 36,\n" + " \"style\": \"bold\", \"name\": \"text1\", \"hOffset\": 250, \"vOffset\": 100, \"alignment\": \"center\",\n" + " \"onMouseUp\": \"sun1.opacity = (sun1.opacity / 100) * 90;\"\n" + " }\n" + "}} \n" + ""; // Number of unicode characters to test at once for JSON escaping private static final int JSON_CHUNK_SIZE = 256; private static void assertJSONArrayEquals(JSONArray expected, JSONArray actual) { assertEquals(expected.size(), actual.size()); for (int i = 0; i < expected.size(); ++i) { assertJSONValueEquals(expected.get(i), actual.get(i)); } } private static void assertJSONObjectEquals(JSONObject expected, JSONObject actual) { Set<String> actKeys = actual.keySet(); Set<String> expKeys = expected.keySet(); assertEquals(expKeys.size(), actKeys.size()); for (String key : expKeys) { assertTrue(actual.containsKey(key)); JSONValue expValue = expected.get(key); JSONValue actValue = actual.get(key); assertJSONValueEquals(expValue, actValue); } } private static void assertJSONValueEquals(JSONValue expected, JSONValue actual) { if (expected.isArray() != null) { JSONArray expArray = expected.isArray(); JSONArray actArray = actual.isArray(); assertJSONArrayEquals(expArray, actArray); } else if (expected.isBoolean() != null) { JSONBoolean expBool = expected.isBoolean(); JSONBoolean actBool = actual.isBoolean(); assertEquals(expBool.booleanValue(), actBool.booleanValue()); } else if (expected.isNull() != null) { assertNotNull(actual.isNull()); } else if (expected.isNumber() != null) { JSONNumber expNum = expected.isNumber(); JSONNumber actNum = actual.isNumber(); assertEquals(expNum.doubleValue(), actNum.doubleValue()); } else if (expected.isObject() != null) { JSONObject expObj = expected.isObject(); JSONObject actObj = actual.isObject(); assertJSONObjectEquals(expObj, actObj); } else if (expected.isString() != null) { JSONString expStr = expected.isString(); JSONString actStr = actual.isString(); assertEquals(expStr.stringValue(), actStr.stringValue()); } else { fail("Unknown JSONValue " + expected); } } /** * Returns the module name for GWT unit test running. */ public String getModuleName() { return "com.google.gwt.json.JSON"; } public void testArrayBasics() { JSONArray a = new JSONArray(); JSONString s = new JSONString("s"); JSONBoolean b = JSONBoolean.getInstance(false); JSONNumber n = new JSONNumber(4); assertNull(a.get(3)); assertNull(a.get(-4)); a.set(3, s); assertEquals(s, a.get(3)); a.set(-4, b); assertEquals(b, a.get(-4)); a.set(2, b); assertEquals(b, a.get(2)); a.set(1, n); assertEquals(n, a.get(1)); } /** * Test deep recursion of arrays. */ public void testArrayOfArraysOfArrays() { JSONArray array = populateRecursiveArray(3, 5); assertEquals( "[[[[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]]],[[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]]],[[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]]]],[[[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]]],[[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]]],[[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]]]],[[[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]]],[[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]]],[[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]],[[[],[],[]],[[],[],[]],[[],[],[]]]]]]", array.toString()); // now to access for (int i = 0; i < 5; i++) { array = (JSONArray) array.get(0); } } /** * Tests an array of raw numbers, like [1,2,3]. */ public void testArrayOfNumbers() { JSONArray arr = new JSONArray(); for (int i = 0; i < 10; i++) { arr.set(i, new JSONNumber(i)); } String s = arr.toString(); JSONValue v = parseStrictVsLenient(s); JSONArray array = v.isArray(); assertTrue("v must be an array", array != null); assertEquals("Array size must be 10", 10, array.size()); for (int i = 0; i < 10; i++) { assertEquals("Array value at " + i + " must be " + i, array.get(i).isNumber().doubleValue(), i, 0.001); } } public void testBooleanBasics() { assertTrue(JSONBoolean.getInstance(true).booleanValue()); assertFalse(JSONBoolean.getInstance(false).booleanValue()); JSONValue trueVal = parseStrictVsLenient("true"); assertEquals(trueVal, trueVal.isBoolean()); assertTrue(trueVal.isBoolean().booleanValue()); JSONValue falseVal = parseStrictVsLenient("false"); assertEquals(falseVal, falseVal.isBoolean()); assertFalse(falseVal.isBoolean().booleanValue()); } public void testEquals() { JSONArray array = parseStrictVsLenient("[]").isArray(); assertEquals(array, new JSONArray(array.getJavaScriptObject())); assertEquals(JSONBoolean.getInstance(false), JSONBoolean.getInstance(false)); assertEquals(JSONBoolean.getInstance(true), JSONBoolean.getInstance(true)); assertEquals(JSONNull.getInstance(), JSONNull.getInstance()); assertEquals(new JSONNumber(3.1), new JSONNumber(3.1)); JSONObject object = parseStrictVsLenient("{}").isObject(); assertEquals(object, new JSONObject(object.getJavaScriptObject())); assertEquals(new JSONString("foo"), new JSONString("foo")); } // Null characters do not work in Development Mode public void testEscaping() { JSONObject o = new JSONObject(); char[] charsToEscape = new char[42]; for (char i = 1; i < 32; i++) { charsToEscape[i] = i; } charsToEscape[32] = '"'; charsToEscape[33] = '\\'; charsToEscape[34] = '\b'; charsToEscape[35] = '\f'; charsToEscape[36] = '\n'; charsToEscape[37] = '\r'; charsToEscape[38] = '\t'; charsToEscape[39] = '/'; charsToEscape[40] = '\u2028'; charsToEscape[41] = '\u2029'; for (int i = 1; i < charsToEscape.length; i++) { o.put("c" + i, new JSONString(new Character(charsToEscape[i]).toString())); } assertEquals("{\"c1\":\"\\u0001\", \"c2\":\"\\u0002\", " + "\"c3\":\"\\u0003\", \"c4\":\"\\u0004\", \"c5\":\"\\u0005\", " + "\"c6\":\"\\u0006\", \"c7\":\"\\u0007\", \"c8\":\"\\b\", " + "\"c9\":\"\\t\", \"c10\":\"\\n\", \"c11\":\"\\u000B\", " + "\"c12\":\"\\f\", \"c13\":\"\\r\", \"c14\":\"\\u000E\", " + "\"c15\":\"\\u000F\", \"c16\":\"\\u0010\", \"c17\":\"\\u0011\", " + "\"c18\":\"\\u0012\", \"c19\":\"\\u0013\", \"c20\":\"\\u0014\", " + "\"c21\":\"\\u0015\", \"c22\":\"\\u0016\", \"c23\":\"\\u0017\", " + "\"c24\":\"\\u0018\", \"c25\":\"\\u0019\", \"c26\":\"\\u001A\", " + "\"c27\":\"\\u001B\", \"c28\":\"\\u001C\", \"c29\":\"\\u001D\", " + "\"c30\":\"\\u001E\", \"c31\":\"\\u001F\", \"c32\":\"\\\"\", " + "\"c33\":\"\\\\\", \"c34\":\"\\b\", \"c35\":\"\\f\", " + "\"c36\":\"\\n\", \"c37\":\"\\r\", \"c38\":\"\\t\", " + "\"c39\":\"/\", \"c40\":\"\\u2028\", \"c41\":\"\\u2029\"}", o.toString()); } public void testHashCode() { JSONArray array = parseStrictVsLenient("[]").isArray(); assertHashCodeEquals(array, new JSONArray(array.getJavaScriptObject())); assertHashCodeEquals(JSONBoolean.getInstance(false), JSONBoolean.getInstance(false)); assertHashCodeEquals(JSONBoolean.getInstance(true), JSONBoolean.getInstance(true)); assertHashCodeEquals(JSONNull.getInstance(), JSONNull.getInstance()); assertHashCodeEquals(new JSONNumber(3.1), new JSONNumber(3.1)); JSONObject object = parseStrictVsLenient("{}").isObject(); assertHashCodeEquals(object, new JSONObject(object.getJavaScriptObject())); assertHashCodeEquals(new JSONString("foo"), new JSONString("foo")); } public void testLargeArrays() { JSONArray arr = null; for (int j = 1; j < 500; j *= 2) { arr = createLargeArray(j); assertEquals("size j" + j, j, arr.size()); } } public void testLenientAndStrict() { String jsonString = "{ a:27, 'b': 'value' }"; // parseLenient should succeed JSONValue value = JSONParser.parseLenient(jsonString); JSONObject object = value.isObject(); assertEquals(27.0, object.get("a").isNumber().doubleValue()); assertEquals("value", object.get("b").isString().stringValue()); // parseStrict should fail try { parseStrictVsLenient(jsonString); fail(); } catch (JSONException e) { } // Must fail even on browsers that lack JSON.parse() jsonString = "function f() { return 5; }"; try { parseStrictVsLenient(jsonString); fail(); } catch (JSONException e) { } } public void testMenu() { JSONObject v = (JSONObject) parseStrictVsLenient(menuTest); assertTrue(v.containsKey("menu")); JSONObject menu = ((JSONObject) v.get("menu")); assertEquals(3, menu.keySet().size()); } public void testNested() { JSONObject obj = new JSONObject(); nestedAux(obj, 3); String s1 = obj.toString(); String s2 = parseStrictVsLenient(s1).toString(); assertEquals(s1, s2); assertEquals( "{\"string3\":\"s3\", \"Number3\":3.1, \"Boolean3\":false, " + "\"Null3\":null, \"object3\":{\"string2\":\"s2\", \"Number2\":2.1, " + "\"Boolean2\":true, \"Null2\":null, \"object2\":{\"string1\":\"s1\"," + " \"Number1\":1.1, \"Boolean1\":false, \"Null1\":null, \"object1\":{" + "\"string0\":\"s0\", \"Number0\":0.1, \"Boolean0\":true, " + "\"Null0\":null, \"object0\":{}, " + "\"Array0\":[\"s0\",0.1,true,null,{}]}, " + "\"Array1\":[\"s1\",1.1,false,null,{\"string0\":\"s0\", " + "\"Number0\":0.1, \"Boolean0\":true, \"Null0\":null, \"object0\":{}, " + "\"Array0\":[\"s0\",0.1,true,null,{}]}]}, " + "\"Array2\":[\"s2\",2.1,true,null,{\"string1\":\"s1\", " + "\"Number1\":1.1, \"Boolean1\":false, \"Null1\":null, " + "\"object1\":{\"string0\":\"s0\", \"Number0\":0.1, " + "\"Boolean0\":true, \"Null0\":null, \"object0\":{}, " + "\"Array0\":[\"s0\",0.1,true,null,{}]}, " + "\"Array1\":[\"s1\",1.1,false,null,{\"string0\":\"s0\", " + "\"Number0\":0.1, \"Boolean0\":true, \"Null0\":null, " + "\"object0\":{}, \"Array0\":[\"s0\",0.1,true,null,{}]}]}]}, " + "\"Array3\":[\"s3\",3.1,false,null,{\"string2\":\"s2\", " + "\"Number2\":2.1, \"Boolean2\":true, \"Null2\":null, " + "\"object2\":{\"string1\":\"s1\", \"Number1\":1.1, " + "\"Boolean1\":false, \"Null1\":null, \"object1\":{\"string0\":\"s0\"," + " \"Number0\":0.1, \"Boolean0\":true, \"Null0\":null, \"object0\":{}, " + "\"Array0\":[\"s0\",0.1,true,null,{}]}, " + "\"Array1\":[\"s1\",1.1,false,null,{\"string0\":\"s0\", " + "\"Number0\":0.1, \"Boolean0\":true, \"Null0\":null, " + "\"object0\":{}, \"Array0\":[\"s0\",0.1,true,null,{}]}]}, " + "\"Array2\":[\"s2\",2.1,true,null,{\"string1\":\"s1\", " + "\"Number1\":1.1, \"Boolean1\":false, \"Null1\":null, " + "\"object1\":{\"string0\":\"s0\", \"Number0\":0.1, " + "\"Boolean0\":true, \"Null0\":null, \"object0\":{}, " + "\"Array0\":[\"s0\",0.1,true,null,{}]}, " + "\"Array1\":[\"s1\",1.1,false,null,{\"string0\":\"s0\", " + "\"Number0\":0.1, \"Boolean0\":true, \"Null0\":null, \"object0\":{}," + " \"Array0\":[\"s0\",0.1,true,null,{}]}]}]}]}", obj.toString()); } public void testNumberBasics() { JSONNumber n0 = new JSONNumber(1000); assertEquals(1000, n0.doubleValue(), .000001); assertTrue(n0.isNumber() == n0); assertNull(n0.isObject()); JSONNumber n1 = new JSONNumber(Integer.MAX_VALUE); assertEquals(Integer.MAX_VALUE, n1.doubleValue(), .00001); assertTrue(n1.isNumber() == n1); assertNull(n1.isObject()); JSONNumber n2 = new JSONNumber(Integer.MIN_VALUE); assertEquals(Integer.MIN_VALUE, n2.doubleValue(), .00001); assertTrue(n2.isNumber() == n2); assertNull(n2.isObject()); } public void testObjectBasics() { JSONObject s = new JSONObject(); assertNull(s.get("buba")); s.put("a", new JSONString("A")); s.put("a", new JSONString("AA")); assertEquals("\"AA\"", s.get("a").toString()); } /** * Tests an object whose keys are filled out with numbers, like {"a":1}. */ public void testObjectOfNumbers() { JSONObject obj = new JSONObject(); for (int i = 0; i < 10; i++) { obj.put("Object " + i, new JSONNumber(i)); } String s = obj.toString(); JSONValue v = parseStrictVsLenient(s); JSONObject objIn = v.isObject(); assertTrue("v must be an object", objIn != null); assertEquals("Object size must be 10", 10, objIn.keySet().size()); for (int i = 0; i < 10; i++) { assertEquals("Object value at 'Object " + i + "' must be " + i, objIn.get("Object " + i).isNumber().doubleValue(), i, 0.001); } } /** * Tests generic parsing. */ public void testParse() { try { new JSONString(null); fail(); } catch (NullPointerException t) { } try { parseStrictVsLenient(null); fail(); } catch (NullPointerException t) { } try { parseStrictVsLenient(""); fail(); } catch (IllegalArgumentException t) { } try { parseStrictVsLenient("{\"menu\": {\n" + " \"id\": \"file\",\n"); fail(); } catch (JSONException e) { } assertEquals("\"null\" should be null JSONValue", JSONNull.getInstance(), parseStrictVsLenient("null")); assertEquals("5 should be JSONNumber 5", 5d, parseStrictVsLenient("5").isNumber().doubleValue(), 0.001); assertEquals("\"null\" should be null JSONValue", JSONNull.getInstance(), parseStrictVsLenient("null")); JSONValue somethingHello = parseStrictVsLenient("[{\"something\":\"hello\"}]"); JSONArray somethingHelloArray = somethingHello.isArray(); assertTrue("somethingHello must be a JSONArray", somethingHelloArray != null); assertTrue("somethingHello size must be one", somethingHelloArray.size() == 1); JSONObject somethingHelloObject = somethingHelloArray.get(0).isObject(); assertTrue("somethingHello element 0 must be a JSONObject", somethingHelloObject != null); assertTrue("somethingHello element 0 must have hello for key something", somethingHelloObject.get("something").isString().stringValue().equals( "hello")); } public void testParseUnescaped() { for (int i = 0; i <= 0xffff; i += JSON_CHUNK_SIZE) { doTestParseUnescaped(i, JSON_CHUNK_SIZE); } } public void testRoundTripEscaping() { JSONObject obj = new JSONObject(); obj.put("a", new JSONNumber(42)); obj.put("\\", new JSONNumber(43.5)); obj.put("\"", new JSONNumber(44)); String toString = obj.toString(); assertEquals("{\"a\":42, \"\\\\\":43.5, \"\\\"\":44}", toString.trim()); JSONValue parseResponse = parseStrictVsLenient(toString); JSONObject obj2 = parseResponse.isObject(); assertJSONObjectEquals(obj, obj2); } public void testSimpleNested() { JSONObject j1 = new JSONObject(); j1.put("test1", new JSONString("")); JSONObject j2 = new JSONObject(); j2.put("test1", new JSONString("")); JSONObject j22 = new JSONObject(); j22.put("test12", new JSONString("")); j2.put("j22", j22); JSONObject j3 = new JSONObject(); j3.put("j1", j1); j3.put("j2", j2); assertEquals( "{\"j1\":{\"test1\":\"\"}, \"j2\":{\"test1\":\"\", \"j22\":{\"test12\":\"\"}}}", j3.toString()); } public void testStringBasics() { JSONString arr = new JSONString(""); assertEquals("\"\"", arr.toString()); JSONString s = new JSONString(menuTest); assertEquals(menuTest, s.stringValue()); } public void testStringEscaping() { checkRoundTripJsonText("\"hello\"", "hello"); checkRoundTripJsonText("\"hel\\\"lo\"", "hel\"lo"); checkRoundTripJsonText("\"hel\\\\lo\"", "hel\\lo"); checkRoundTripJsonText("\"hel\\\\\\\"lo\"", "hel\\\"lo"); } public void testStringTypes() { JSONObject object = parseStrictVsLenient("{\"a\":\"b\",\"null\":\"foo\"}").isObject(); assertNotNull(object); assertEquals("b", object.get(stringAsPrimitive("a")).isString().stringValue()); assertEquals("b", object.get(stringAsObject("a")).isString().stringValue()); assertEquals("foo", object.get(stringAsPrimitive("null")).isString().stringValue()); assertEquals("foo", object.get(stringAsObject("null")).isString().stringValue()); try { assertNull(object.get(null)); fail("Expected NullPointerException"); } catch (NullPointerException expected) { } } public void testUndefined() { JSONObject o = parseStrictVsLenient("{\"foo\":\"foo\",\"bar\":null}").isObject(); assertEquals(new JSONString("foo"), o.get("foo")); assertEquals(JSONNull.getInstance(), o.get("bar")); assertNull(o.get("baz")); o.put("foo", JSONNull.getInstance()); assertEquals(JSONNull.getInstance(), o.get("foo")); o.put("foo", null); assertNull(o.get("foo")); JSONArray array = parseStrictVsLenient("[\"foo\",null]").isArray(); assertEquals(new JSONString("foo"), array.get(0)); assertEquals(JSONNull.getInstance(), array.get(1)); assertNull(array.get(2)); array.set(0, JSONNull.getInstance()); assertEquals(JSONNull.getInstance(), array.get(0)); array.set(0, null); assertNull(array.get(0)); } public void testUnicodeSeparators() { /* * ECMAScript 5 allows unescaped U+2028 (line separator) and U+2029 * (paragraph separator) characters to occur inside strings. */ String jsonString = "{ \"name\": \"miles\u2028da\u2029vis\", \"ins\u2028tru\u2029ment\": \"trumpet\" }"; try { JSONValue parsed = parseStrictVsLenient(jsonString); JSONObject result = parsed.isObject(); assertNotNull(result); JSONValue nameValue = result.get("name"); assertNotNull(nameValue); JSONString nameJsonString = nameValue.isString(); assertNotNull(nameJsonString); String nameString = nameJsonString.stringValue(); assertEquals("miles\u2028da\u2029vis", nameString); String nameStringQuoted = nameJsonString.toString(); assertEquals("\"miles\\u2028da\\u2029vis\"", nameStringQuoted); JSONValue instrumentValue = result.get("ins\u2028tru\u2029ment"); assertNotNull(instrumentValue); JSONValue instrumentValue2 = result.get("instrument"); assertNull(instrumentValue2); // check no name collision JSONString instrumentJsonString = instrumentValue.isString(); assertNotNull(instrumentJsonString); String instrumentString = instrumentJsonString.stringValue(); assertEquals("trumpet", instrumentString); } catch (JSONException e) { fail(e.getMessage()); } // U+2028 and U+2029 should not appear outside a string jsonString = "{ \"name\": \"miles davis\",\u2028\"instrument\": \"trumpet\" }"; try { parseStrictVsLenient(jsonString); fail(); } catch (JSONException e) { } jsonString = "{ \"name\":\u2029\"miles davis\", \"instrument\": \"trumpet\" }"; try { parseStrictVsLenient(jsonString); fail(); } catch (JSONException e) { } } public void testUnsafeEval() { JsonUtils.unsafeEval("{\"name\":\"value\"}"); JsonUtils.unsafeEval("[0,1,2,3,4]"); } public void testWidget() { JSONObject v = (JSONObject) parseStrictVsLenient(widgetTest); JSONObject widget = (JSONObject) v.get("widget"); JSONObject window = (JSONObject) widget.get("window"); JSONValue title = window.get("title"); assertNotNull(title.isString()); JSONValue hOffSet = window.get("width"); assertNotNull(hOffSet.isNumber()); } private void assertHashCodeEquals(Object expected, Object actual) { assertEquals("hashCodes are not equal", expected.hashCode(), actual.hashCode()); } private void checkRoundTripJsonText(String jsonText, String normaltext) { JSONString parsed = parseStrictVsLenient(jsonText).isString(); assertEquals(normaltext, parsed.stringValue()); assertEquals(jsonText, parsed.toString()); } private JSONArray createLargeArray(int size) { JSONArray arr = new JSONArray(); for (int i = 0; i < size; i++) { arr.set(i, new JSONNumber(i)); } return arr; } /** * Test a chunk of Unicode code points for use in JSON keys and values. * * @param start starting code point * @param len number of code points to test */ private void doTestParseUnescaped(int start, int len) { StringBuilder sb = new StringBuilder(); for (int i = start; i < start + len; i++) { // Skip control characters if (i < 0x20) { continue; } // Skip surrogate pairs if (i >= 0xD800 && i <= 0xDFFF) { continue; } char c = (char) i; // Skip quote and backslash if (c == '\"' || c == '\\') { continue; } sb.append(c); } String chars = sb.toString(); if (chars.length() == 0) { return; } String key = "na" + chars + "me"; String value = "miles" + chars + "davis"; String jsonString = "{ \"" + key + "\": \"" + value + "\"}"; try { JSONValue parsed = parseStrictVsLenient(jsonString); JSONObject result = parsed.isObject(); assertNotNull("start = " + start + ", len = " + len, result); Set<String> keys = result.keySet(); assertTrue("start = " + start + ", len = " + len, keys.contains(key)); JSONValue nameValue = result.get(key); assertNotNull("start = " + start + ", len = " + len, nameValue); JSONString nameJsonString = nameValue.isString(); assertNotNull("start = " + start + ", len = " + len, nameJsonString); String nameString = nameJsonString.stringValue(); assertEquals("start = " + start + ", len = " + len, value, nameString); } catch (JSONException e) { fail("start = " + start + ", len = " + len + ", e = " + e.getMessage()); } } private void nestedAux(JSONObject obj, int i) { JSONArray array = new JSONArray(); JSONString str = new JSONString("s" + i); array.set(0, str); obj.put("string" + i, str); JSONNumber num = new JSONNumber(i + 0.1); array.set(1, num); obj.put("Number" + i, num); JSONBoolean b = JSONBoolean.getInstance((i % 2) == 0); array.set(2, b); obj.put("Boolean" + i, b); JSONNull nul = JSONNull.getInstance(); array.set(3, nul); obj.put("Null" + i, nul); JSONObject newObj = new JSONObject(); obj.put("object" + i, newObj); if (i != 0) { nestedAux(newObj, i - 1); } array.set(4, newObj); obj.put("Array" + i, array); } // Check that parseLenient produces the same results as parseStrict private JSONValue parseStrictVsLenient(String jsonString) { JSONValue strictValue = JSONParser.parseStrict(jsonString); JSONValue lenientValue = JSONParser.parseLenient(jsonString); assertJSONValueEquals(strictValue, lenientValue); return strictValue; } private JSONArray populateRecursiveArray(int numElements, int recursion) { JSONArray newArray = new JSONArray(); if (recursion <= 0) { return newArray; } for (int i = 0; i < numElements; i++) { JSONArray childArray = populateRecursiveArray(numElements, recursion - 1); newArray.set(i, childArray); } return newArray; } private native String stringAsObject(String str) /*-{ return new String(str); }-*/; private native String stringAsPrimitive(String str) /*-{ return String(str); }-*/; }