Author: rwhitcomb
Date: Wed Apr 22 23:26:15 2015
New Revision: 1675517

URL: http://svn.apache.org/r1675517
Log:
PIVOT-967: Fix the JSONSerializer to correctly deal with special characters
inside string values (especially \r and others).

Add the ability to directly support java.util.Map values in an object
passed to JSONSerializer.writeObject (by instantiating a MapAdapter around
the java.util.Map object).

Update the JSONSerializerTest to test these changes (both read and write).
Update the "map.json" with test values.

Modified:
    pivot/trunk/core/src/org/apache/pivot/json/JSONSerializer.java
    pivot/trunk/core/test/org/apache/pivot/json/test/JSONSerializerTest.java
    pivot/trunk/core/test/org/apache/pivot/json/test/map.json

Modified: pivot/trunk/core/src/org/apache/pivot/json/JSONSerializer.java
URL: 
http://svn.apache.org/viewvc/pivot/trunk/core/src/org/apache/pivot/json/JSONSerializer.java?rev=1675517&r1=1675516&r2=1675517&view=diff
==============================================================================
--- pivot/trunk/core/src/org/apache/pivot/json/JSONSerializer.java (original)
+++ pivot/trunk/core/src/org/apache/pivot/json/JSONSerializer.java Wed Apr 22 
23:26:15 2015
@@ -40,6 +40,7 @@ import org.apache.pivot.collections.Hash
 import org.apache.pivot.collections.List;
 import org.apache.pivot.collections.Map;
 import org.apache.pivot.collections.Sequence;
+import org.apache.pivot.collections.adapter.MapAdapter;
 import org.apache.pivot.io.EchoReader;
 import org.apache.pivot.io.EchoWriter;
 import org.apache.pivot.serialization.MacroReader;
@@ -378,6 +379,8 @@ public class JSONSerializer implements S
         c = reader.read();
 
         while (c != -1 && c != t) {
+            // The JSON spec says that control characters are not supported,
+            // so silently ignore them
             if (!Character.isISOControl(c)) {
                 if (c == '\\') {
                     c = reader.read();
@@ -875,6 +878,21 @@ public class JSONSerializer implements S
                         break;
                     }
 
+                    case '\r': {
+                        stringBuilder.append("\\r");
+                        break;
+                    }
+
+                    case '\f': {
+                        stringBuilder.append("\\f");
+                        break;
+                    }
+
+                    case '\b': {
+                        stringBuilder.append("\\b");
+                        break;
+                    }
+
                     case '\\':
                     case '\"':
                     case '\'': {
@@ -883,7 +901,10 @@ public class JSONSerializer implements S
                     }
 
                     default: {
-                        if (charset.name().startsWith("UTF") || ci <= 0xFF) {
+                        // For Unicode character sets if it is a control 
character, then use \\uXXXX notation
+                        // and for other character sets if the value is an 
ASCII control character.
+                        if ((charset.name().startsWith("UTF") && 
!Character.isISOControl(ci)) ||
+                            (ci > 0x1F && ci != 0x7F && ci <= 0xFF)) {
                             stringBuilder.append(ci);
                         } else {
                             stringBuilder.append("\\u");
@@ -932,6 +953,8 @@ public class JSONSerializer implements S
             Map<String, Object> map;
             if (object instanceof Map<?, ?>) {
                 map = (Map<String, Object>) object;
+            } else if (object instanceof java.util.Map<?, ?>) {
+                map = new MapAdapter<>((java.util.Map<String, Object>)object);
             } else {
                 map = new BeanAdapter(object, true);
             }

Modified: 
pivot/trunk/core/test/org/apache/pivot/json/test/JSONSerializerTest.java
URL: 
http://svn.apache.org/viewvc/pivot/trunk/core/test/org/apache/pivot/json/test/JSONSerializerTest.java?rev=1675517&r1=1675516&r2=1675517&view=diff
==============================================================================
--- pivot/trunk/core/test/org/apache/pivot/json/test/JSONSerializerTest.java 
(original)
+++ pivot/trunk/core/test/org/apache/pivot/json/test/JSONSerializerTest.java 
Wed Apr 22 23:26:15 2015
@@ -139,6 +139,7 @@ public class JSONSerializerTest {
         assertEquals(JSON.get(o1, "e.g"), 5);
         assertEquals(JSON.get(o1, "i.a"), 200);
         assertEquals(JSON.get(o1, "i.c"), true);
+        assertEquals(JSON.get(o1, "m"), "Hello\r\n\tWorld!");
 
         
jsonSerializer.getJSONSerializerListeners().remove(jsonSerializerListener);
         Object o2 = 
jsonSerializer.readObject(getClass().getResourceAsStream("map.json"));
@@ -147,6 +148,7 @@ public class JSONSerializerTest {
         assertEquals(JSON.get(o2, "k[2].b"), 200);
         assertEquals(JSON.get(o2, "k[2].c"), "300");
         assertEquals(JSON.get(o2, "j"), 200);
+        assertEquals(JSON.get(o2, "n"), "This is a \"test\" of the 'quoting' 
in \\JSON\\");
 
         assertTrue(o1.equals(o2));
 
@@ -157,18 +159,25 @@ public class JSONSerializerTest {
     }
 
     @Test
-    public void testJavaMap() {
+    public void testJavaMap() throws SerializationException {
         System.out.println("Test interaction with Standard java.util.Map");
 
         java.util.HashMap<String, java.util.Map<String, String>> root = new 
java.util.HashMap<>();
         java.util.HashMap<String, String> child = new java.util.HashMap<>();
 
         child.put("name", "John Doe");
+        child.put("address", "123 Main St.\r\nAnytown USA");
         root.put("child", child);
 
         String childName = JSON.get(root, "child.name");
-        System.out.println("JSON child.name = \"" + childName + "\"");
+        String childAddr = JSON.get(root, "child.address");
+        System.out.println("JSON child.name = \"" + childName + "\", 
child.address = \"" + childAddr + "\"");
         assertEquals(childName, "John Doe");
+        assertEquals(childAddr, "123 Main St.\r\nAnytown USA");
+
+        String serializedForm = JSONSerializer.toString(root);
+        System.out.println("Serialized form: \"" + serializedForm + "\"");
+        assertEquals(serializedForm, "{child: {address: \"123 Main 
St.\\r\\nAnytown USA\", name: \"John Doe\"}}");
     }
 
 }

Modified: pivot/trunk/core/test/org/apache/pivot/json/test/map.json
URL: 
http://svn.apache.org/viewvc/pivot/trunk/core/test/org/apache/pivot/json/test/map.json?rev=1675517&r1=1675516&r2=1675517&view=diff
==============================================================================
--- pivot/trunk/core/test/org/apache/pivot/json/test/map.json (original)
+++ pivot/trunk/core/test/org/apache/pivot/json/test/map.json Wed Apr 22 
23:26:15 2015
@@ -29,11 +29,13 @@
 {   ${A_B_C},
     d: ["1", "2", "${THREE}"],
     e: {f: 4, g: 5, h: 6},
-    "i": { a: ${TWO_HUNDRED}, b: "Goodbye", c: true},
+    "i": { a: ${TWO_HUNDRED}, b: "Goodbye", c: true },
     j: ${TWO_HUNDRED},
     k:  [
         {a:1, b:2, c:"${THREE}"},
         {a:1${ZERO}, b:${TWENTY}, c:"${THIRTY}"},
         {a:1${ZERO}${ZERO}, b:${TWO_HUNDRED}, c:"${THREE_HUNDRED}"}
-    ]
+    ],
+    m: "Hello\r\n\tWorld!",
+    n: "This is a \"test\" of the \'quoting\' in \\JSON\\"
 }


Reply via email to