Bug 2147 - JSON does not properly encode multiline string 08/12008/1
authorJan Hajnar <jhajnar@cisco.com>
Wed, 15 Oct 2014 12:54:37 +0000 (14:54 +0200)
committerTony Tkacik <ttkacik@cisco.com>
Thu, 16 Oct 2014 12:58:56 +0000 (12:58 +0000)
* added newline and return characters to escape list
* updated tests

Change-Id: I48cd418b1633de12e80bdab0b7c7bc91113dbf6d
Signed-off-by: Jan Hajnar <jhajnar@cisco.com>
(cherry picked from commit e6c3a206a204de77c70df1c0940a088493401749)

yang/yang-data-codec-gson/src/main/java/org/opendaylight/yangtools/yang/data/codec/gson/JSONNormalizedNodeStreamWriter.java
yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/NormalizedNodeToJsonStreamTest.java
yang/yang-data-codec-gson/src/test/java/org/opendaylight/yangtools/yang/data/codec/gson/TestingNormalizedNodeStructuresCreator.java

index 8fcc596ab47ebe3e8e5d2ed86ecb00f8cc2d104e..e1bba78be001caa2977611544256ff23e5ffd510 100644 (file)
@@ -11,9 +11,6 @@ import com.google.common.base.CharMatcher;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.gson.stream.JsonWriter;
-import java.io.IOException;
-import java.io.Writer;
-import java.net.URI;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
@@ -26,6 +23,10 @@ import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 
+import java.io.IOException;
+import java.io.Writer;
+import java.net.URI;
+
 /**
  * This implementation will create JSON output as output stream.
  *
@@ -43,7 +44,7 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite
     /**
      * Matcher used to check if a string needs to be escaped.
      */
-    private static final CharMatcher QUOTES_OR_BACKSLASH = CharMatcher.anyOf("\\\"");
+    private static final CharMatcher JSON_ILLEGAL_STRING_CHARACTERS = CharMatcher.anyOf("\\\"\n\r");
 
     private final SchemaTracker tracker;
     private final JSONCodecFactory codecs;
@@ -228,14 +229,14 @@ public class JSONNormalizedNodeStreamWriter implements NormalizedNodeStreamWrite
         if (needQuotes) {
             writer.append('"');
 
-            final int needEscape = QUOTES_OR_BACKSLASH.countIn(str);
+            final int needEscape = JSON_ILLEGAL_STRING_CHARACTERS.countIn(str);
             if (needEscape != 0) {
                 final char[] escaped = new char[str.length() + needEscape];
                 int offset = 0;
 
                 for (int i = 0; i < str.length(); i++) {
                     final char c = str.charAt(i);
-                    if (QUOTES_OR_BACKSLASH.matches(c)) {
+                    if (JSON_ILLEGAL_STRING_CHARACTERS.matches(c)) {
                         escaped[offset++] = '\\';
                     }
                     escaped[offset++] = c;
index 62e7cf18cd8ce742beebabe5971d5bdd60b2143c..39a1f1bc7bbe30c9cd131cd581d7269650ed4b0a 100644 (file)
@@ -7,26 +7,11 @@
  */
 package org.opendaylight.yangtools.yang.data.codec.gson;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.childArray;
-import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.childPrimitive;
-import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.loadModules;
-import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.resolveCont1;
-
 import com.google.common.collect.Sets;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonPrimitive;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.net.URISyntaxException;
-import java.util.HashSet;
-import java.util.Iterator;
 import org.junit.BeforeClass;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -35,6 +20,22 @@ import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStre
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URISyntaxException;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.childArray;
+import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.childPrimitive;
+import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.loadModules;
+import static org.opendaylight.yangtools.yang.data.codec.gson.TestUtils.resolveCont1;
+
 /**
  * Each test tests whether json output obtained after transformation contains is corect. The transformation takes
  * normalized node data structure and transform it to json output. To make it easier validate json output it is loaded
@@ -95,6 +96,32 @@ public class NormalizedNodeToJsonStreamTest {
 
     }
 
+    @Test
+    public void leafListNodeInContainerMultiline() throws IOException, URISyntaxException {
+        Writer writer = new StringWriter();
+        NormalizedNode<?, ?> leafListNodeInContainer = TestingNormalizedNodeStructuresCreator.leafListNodeInContainerMultiline();
+        String jsonOutput = normalizedNodeToJsonStreamTransformation(writer, leafListNodeInContainer);
+        new JsonValidator() {
+
+            @Override
+            public void validate(String jsonOutput) {
+                JsonObject cont1 = resolveCont1(jsonOutput);
+                assertNotNull(cont1);
+                JsonArray lflst11 = childArray(cont1, "complexjson:lflst11", "lflst11");
+                assertNotNull(lflst11);
+
+                HashSet<Object> lflst11Values = Sets.newHashSet();
+                for (JsonElement jsonElement : lflst11) {
+                    assertTrue(jsonElement instanceof JsonPrimitive);
+                    lflst11Values.add(((JsonPrimitive) jsonElement).getAsString());
+                }
+
+                assertEquals(Sets.newHashSet("lflst11 value2\r\nanother line 2", "lflst11 value1\nanother line 1"), lflst11Values);
+            }
+        }.validate(jsonOutput);
+
+    }
+
     @Test
     public void leafNodeViaAugmentationInContainer() throws IOException, URISyntaxException {
         Writer writer = new StringWriter();
index f1400854d9d76d2840849a0d8c6b9a5a3165ab94..1038ce883db6d8389f6ed15a77cc243b05011e0a 100644 (file)
@@ -9,8 +9,6 @@ package org.opendaylight.yangtools.yang.data.codec.gson;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
-import java.util.HashMap;
-import java.util.Map;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
@@ -40,6 +38,9 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContaine
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
 
+import java.util.HashMap;
+import java.util.Map;
+
 public class TestingNormalizedNodeStructuresCreator {
 
     static NormalizedNode<?, ?> cont1Node(
@@ -236,6 +237,22 @@ public class TestingNormalizedNodeStructuresCreator {
         return lflst11.build();
     }
 
+    private static DataContainerChild<? extends PathArgument, ?> childLflst11Multiline() {
+        ListNodeBuilder<Object, LeafSetEntryNode<Object>> lflst11 = Builders.leafSetBuilder().withNodeIdentifier(
+                new NodeIdentifier(QName.create("ns:complex:json", "2014-08-11", "lflst11")));
+        lflst11.withChild(Builders
+                .leafSetEntryBuilder()
+                .withNodeIdentifier(
+                        new NodeWithValue(QName.create("ns:complex:json", "2014-08-11", "lflst11"), "lflst11 value1\nanother line 1"))
+                .withValue("lflst11 value1\nanother line 1").build());
+        lflst11.withChild(Builders
+                .leafSetEntryBuilder()
+                .withNodeIdentifier(
+                        new NodeWithValue(QName.create("ns:complex:json", "2014-08-11", "lflst11"), "lflst11 value2\r\nanother line 2"))
+                .withValue("lflst11 value2\r\nanother line 2").build());
+        return lflst11.build();
+    }
+
     private static CompositeNode prepareLf12Value() {
         SimpleNode<?> anyxmlInData = NodeFactory.createImmutableSimpleNode(
                 QName.create("ns:complex:json", "2014-08-11", "anyxml-in-data"), null, "foo");
@@ -260,6 +277,9 @@ public class TestingNormalizedNodeStructuresCreator {
     public static NormalizedNode<?, ?> leafListNodeInContainer() {
         return cont1Node(childLflst11());
     }
+    public static NormalizedNode<?, ?> leafListNodeInContainerMultiline() {
+        return cont1Node(childLflst11Multiline());
+    }
 
     public static NormalizedNode<?, ?> keyedListNodeInContainer() {
         return cont1Node(childLst11());