From 482d788e76872e97b5ef7c39bb68059c9fe5d9d7 Mon Sep 17 00:00:00 2001 From: mizady <90141999+mizady@users.noreply.github.com> Date: Fri, 13 Dec 2024 16:30:00 -0500 Subject: [PATCH] Added already deserialized bypass and tests Added a bypass to return a string that as already been deserialized when it lands at StringConverter.ToType() Removed portion of string escape character processing in JsonConvert as it was implemented in StringConverter (unicode escaped character processing still remains in JsonConvert) Added Tests for multiple escaped characters in a string and in an object containing a string property. Added test case for string converter test for serializing and deserializing strings with multiple escaped characters --- .../Converters/StringConverterTests.cs | 2 + .../JsonSerializerOptionsTests.cs | 28 ++++++++++ .../Converters/StringConverter.cs | 14 ++++- nanoFramework.Json/JsonConvert.cs | 54 ++++++++++--------- 4 files changed, 72 insertions(+), 26 deletions(-) diff --git a/nanoFramework.Json.Test/Converters/StringConverterTests.cs b/nanoFramework.Json.Test/Converters/StringConverterTests.cs index 92dcd50b..4cb96195 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 78f3c8fc..f0f998af 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 a9f77a0f..02194053 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 2a320ea1..4f10b5a9 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)))