Fixes issue 2008. Corrects JSONObject's toString to properly escape backslashes and quotes. Issue: 2008 Patch by: fredsa, jat Review by: scottb git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1963 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/json/client/JSONObject.java b/user/src/com/google/gwt/json/client/JSONObject.java index b1fe522..84043e7 100644 --- a/user/src/com/google/gwt/json/client/JSONObject.java +++ b/user/src/com/google/gwt/json/client/JSONObject.java
@@ -185,9 +185,8 @@ var subObj = (this.@com.google.gwt.json.client.JSONObject::frontStore[key]). @com.google.gwt.json.client.JSONValue::toString()(); - out.push("\""); - out.push(key); - out.push("\":"); + out.push(@com.google.gwt.json.client.JSONString::escapeValue(Ljava/lang/String;)(key)); + out.push(":"); out.push(subObj); } out.push("}")
diff --git a/user/src/com/google/gwt/json/client/JSONString.java b/user/src/com/google/gwt/json/client/JSONString.java index fbd824e..73bce23 100644 --- a/user/src/com/google/gwt/json/client/JSONString.java +++ b/user/src/com/google/gwt/json/client/JSONString.java
@@ -29,6 +29,13 @@ return (lookedUp == null) ? c : lookedUp; }-*/; + static native String escapeValue(String toEscape) /*-{ + var s = toEscape.replace(/[\x00-\x1F"\\]/g, function(x) { + return @com.google.gwt.json.client.JSONString::escapeChar(Ljava/lang/String;)(x); + }); + return "\"" + s + "\""; + }-*/; + private static native JavaScriptObject initEscapeTable() /*-{ var out = [ "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", @@ -80,11 +87,4 @@ public String toString() { return escapeValue(value); } - - private native String escapeValue(String toEscape) /*-{ - var s = toEscape.replace(/[\x00-\x1F"\\]/g, function(x) { - return @com.google.gwt.json.client.JSONString::escapeChar(Ljava/lang/String;)(x); - }); - return "\"" + s + "\""; - }-*/; }
diff --git a/user/test/com/google/gwt/json/client/JSONTest.java b/user/test/com/google/gwt/json/client/JSONTest.java index e5a9feb..d946328 100644 --- a/user/test/com/google/gwt/json/client/JSONTest.java +++ b/user/test/com/google/gwt/json/client/JSONTest.java
@@ -17,8 +17,10 @@ import com.google.gwt.junit.client.GWTTestCase; +import java.util.Set; + /** - * TODO: document me. + * Test case for JSONValue and friends. */ public class JSONTest extends GWTTestCase { static final String menuTest = "{\"menu\": {\n" + " \"id\": \"file\",\n" @@ -43,6 +45,54 @@ + " \"onMouseUp\": \"sun1.opacity = (sun1.opacity / 100) * 90;\"\n" + " }\n" + "}} \n" + ""; + 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(); + for (String key : expected.keySet()) { + actKeys.remove(key); + assertTrue(actual.containsKey(key)); + JSONValue expValue = expected.get(key); + JSONValue actValue = actual.get(key); + assertJSONValueEquals(expValue, actValue); + } + assertEquals(0, actKeys.size()); + } + + 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.getValue(), actNum.getValue()); + } 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. */ @@ -294,6 +344,19 @@ "hello")); } + public void testRoundTripEscaping() { + JSONObject obj = new JSONObject(); + obj.put("a", new JSONNumber(42)); + obj.put("\\", new JSONNumber(43)); + obj.put("\"", new JSONNumber(44)); + + String toString = obj.toString(); + assertEquals("{\"a\":42.0, \"\\\\\":43.0, \"\\\"\":44.0}", toString.trim()); + JSONValue parseResponse = JSONParser.parse(toString); + JSONObject obj2 = parseResponse.isObject(); + assertJSONObjectEquals(obj, obj2); + } + public void testSimpleNested() { JSONObject j1 = new JSONObject(); j1.put("test1", new JSONString("")); @@ -332,10 +395,13 @@ JSONObject object = JSONParser.parse("{\"a\":\"b\",\"null\":\"foo\"}").isObject(); assertNotNull(object); - assertEquals("b", object.get(stringAsPrimitive("a")).isString().stringValue()); + 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()); + assertEquals("foo", + object.get(stringAsPrimitive("null")).isString().stringValue()); + assertEquals("foo", + object.get(stringAsObject("null")).isString().stringValue()); assertNull(object.get(null)); }