diff --git a/nanoFramework.Json.Test/Converters/StringConverterTests.cs b/nanoFramework.Json.Test/Converters/StringConverterTests.cs index 92dcd50..4cb9619 100644 --- a/nanoFramework.Json.Test/Converters/StringConverterTests.cs +++ b/nanoFramework.Json.Test/Converters/StringConverterTests.cs @@ -51,6 +51,7 @@ public void StringConverter_ToJson_Should_ReturnValidData(string value, string e [DataRow("['Text3', 1]", "['Text3', 1]")] // Array [DataRow("{\"Text1\" : \"/Text1/\"}", "{\"Text1\" : \"/Text1/\"}")] // Json [DataRow("ä", "ä")] // Unicode + [DataRow("\"I:\\\\nano\\\\rpath\\\\to\"", "I:\\nano\\rpath\\to")] public void StringConverter_ToType_Should_HandleSpecialCharacters(string value, string expectedValue) { var converter = new Json.Converters.StringConverter(); @@ -68,6 +69,7 @@ public void StringConverter_ToType_Should_HandleSpecialCharacters(string value, [DataRow("Text\n1", "\"Text\\n1\"")] // Newline [DataRow("Text\t1", "\"Text\\t1\"")] // Tab [DataRow("ä", "\"ä\"")] // Unicode + [DataRow("I:\\nano\\rpath\\to", "\"I:\\\\nano\\\\rpath\\\\to\"")] public void StringConverter_ToJson_Should_HandleSpecialCharacters(string value, string expectedValue) { var converter = new Json.Converters.StringConverter(); diff --git a/nanoFramework.Json.Test/JsonSerializerOptionsTests.cs b/nanoFramework.Json.Test/JsonSerializerOptionsTests.cs index 78f3c8f..f0f998a 100644 --- a/nanoFramework.Json.Test/JsonSerializerOptionsTests.cs +++ b/nanoFramework.Json.Test/JsonSerializerOptionsTests.cs @@ -387,6 +387,34 @@ public void Can_serialize_and_deserialize_escaped_string() Assert.AreEqual(thing.Value, deserialized.Value); } + [TestMethod] + public void Can_serialize_and_deserialize_object_containing_string_with_multiple_escaped_characters() + { + var thing = new ThingWithString + { + Value = "I:\\Nano\\rApp\\app.pe" + }; + + var serialized = JsonConvert.SerializeObject(thing); + var deserialized = (ThingWithString)JsonConvert.DeserializeObject(serialized, typeof(ThingWithString)); + Assert.AreEqual(thing.Value, deserialized.Value); + } + + [TestMethod] + public void Can_serialize_and_deserialize_string_with_multiple_escaped_characters() + { + var testValue = "I:\\Nano\\rApp\\app.pe"; + Console.WriteLine("Original: " + testValue); + + var serialized = JsonConvert.SerializeObject(testValue); + Console.WriteLine("Serialized: " + serialized); + + var deserialized = (string)JsonConvert.DeserializeObject(serialized, typeof(string)); + Console.WriteLine("Deserialized: " + deserialized); + + Assert.AreEqual(testValue, deserialized); + } + [TestMethod] public void Can_serialize_and_deserialize_complex_object() { diff --git a/nanoFramework.Json/Converters/StringConverter.cs b/nanoFramework.Json/Converters/StringConverter.cs index a9f77a0..0219405 100644 --- a/nanoFramework.Json/Converters/StringConverter.cs +++ b/nanoFramework.Json/Converters/StringConverter.cs @@ -101,8 +101,18 @@ public object ToType(object value) return value; } - //String by default has escaped \" at beggining and end, just remove them - var resultString = sourceString.Substring(1, sourceString.Length - 2); + string resultString; + + // String by default has escaped \" at beggining and end, just remove them + // if they have already been removed, string has likely already been deserialized, + // and if so, then we just return it. + if (!sourceString.StartsWith("\"") && !sourceString.EndsWith("\"")) + { + return sourceString; + } + + resultString = sourceString.Substring(1, sourceString.Length - 2); + var newString = new StringBuilder(); //Last character can not be escaped, because it's last one for (int i = 0; i < resultString.Length - 1; i++) diff --git a/nanoFramework.Json/JsonConvert.cs b/nanoFramework.Json/JsonConvert.cs index 2a320ea..4f10b5a 100644 --- a/nanoFramework.Json/JsonConvert.cs +++ b/nanoFramework.Json/JsonConvert.cs @@ -1088,32 +1088,38 @@ private static LexToken GetNextTokenInternal(ref int jsonPos, ref byte[] jsonByt return EndToken(sb); } - //TODO: replace with a mapping array? This switch is really incomplete. - switch (ch) + if(ch == 'u') { - case 't': - ch = '\t'; - break; - - case 'r': - ch = '\r'; - break; - - case 'n': - ch = '\n'; - break; - - case 'u': - unicodeEncoded = true; - break; - - case '"': - ch = '"'; - break; - - default: - throw new DeserializationException(); + unicodeEncoded = true; } + + //TODO: replace with a mapping array? This switch is really incomplete. + // Has been moved to StringConverter but unicode part still remains here + //switch (ch) + //{ + // case 't': + // ch = '\t'; + // break; + + // case 'r': + // ch = '\r'; + // break; + + // case 'n': + // ch = '\n'; + // break; + + // case 'u': + // unicodeEncoded = true; + // break; + + // case '"': + // ch = '"'; + // break; + + // default: + // throw new DeserializationException(); + //} } if ((sb != null) && ((ch != openQuote) || (escaped)))