From af6e7b9c13b80c5fef38204a7543e38cc532961d Mon Sep 17 00:00:00 2001 From: James Newton-King Date: Sat, 13 Nov 2021 15:06:40 +1300 Subject: [PATCH] Refactor type name multidimensional array support and add tests --- .../Serialization/TypeNameHandlingTests.cs | 119 ++++++++++++++++++ .../TestObjects/HasByteArray.cs | 6 + .../Utilities/ReflectionUtils.cs | 10 +- 3 files changed, 130 insertions(+), 5 deletions(-) diff --git a/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs b/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs index 2b65d0aa..ccb5543c 100644 --- a/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs +++ b/Src/Newtonsoft.Json.Tests/Serialization/TypeNameHandlingTests.cs @@ -62,6 +62,125 @@ namespace Newtonsoft.Json.Tests.Serialization [TestFixture] public class TypeNameHandlingTests : TestFixtureBase { + [Test] + public void SerializeMultidimensionalByteArrayWithTypeName() + { + string array2dRef = ReflectionUtils.GetTypeName(typeof(byte[,]), TypeNameAssemblyFormatHandling.Simple, null); + string array3dRef = ReflectionUtils.GetTypeName(typeof(byte[,,]), TypeNameAssemblyFormatHandling.Simple, null); + + HasMultidimensionalByteArray o = new HasMultidimensionalByteArray + { + Array2D = new byte[,] { { 1, 2 }, { 2, 4 }, { 3, 6 } }, + Array3D = new byte[,,] { { { 1, 2, 3}, { 4, 5, 6 } } } + }; + + string json = JsonConvert.SerializeObject(o, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.All, + Formatting = Formatting.Indented + }); + + string expectedJson = @"{ + ""$type"": ""Newtonsoft.Json.Tests.TestObjects.HasMultidimensionalByteArray, Newtonsoft.Json.Tests"", + ""Array2D"": { + ""$type"": """ + array2dRef + @""", + ""$values"": [ + [ + 1, + 2 + ], + [ + 2, + 4 + ], + [ + 3, + 6 + ] + ] + }, + ""Array3D"": { + ""$type"": """ + array3dRef + @""", + ""$values"": [ + [ + [ + 1, + 2, + 3 + ], + [ + 4, + 5, + 6 + ] + ] + ] + } +}"; + + StringAssert.AreEqual(expectedJson, json); + } + + + [Test] + public void DeserializeMultidimensionalByteArrayWithTypeName() + { + string json = @"{ + ""$type"": ""Newtonsoft.Json.Tests.TestObjects.HasMultidimensionalByteArray, Newtonsoft.Json.Tests"", + ""Array2D"": { + ""$type"": ""System.Byte[,], mscorlib"", + ""$values"": [ + [ + 1, + 2 + ], + [ + 2, + 4 + ], + [ + 3, + 6 + ] + ] + }, + ""Array3D"": { + ""$type"": ""System.Byte[,,], mscorlib"", + ""$values"": [ + [ + [ + 1, + 2, + 3 + ], + [ + 4, + 5, + 6 + ] + ] + ] + } +}"; + HasMultidimensionalByteArray value = JsonConvert.DeserializeObject(json, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.Objects + }); + + Assert.AreEqual(1, value.Array2D[0, 0]); + Assert.AreEqual(2, value.Array2D[0, 1]); + Assert.AreEqual(2, value.Array2D[1, 0]); + Assert.AreEqual(4, value.Array2D[1, 1]); + Assert.AreEqual(3, value.Array2D[2, 0]); + Assert.AreEqual(6, value.Array2D[2, 1]); + + Assert.AreEqual(1, value.Array3D[0, 0, 0]); + Assert.AreEqual(2, value.Array3D[0, 0, 1]); + Assert.AreEqual(3, value.Array3D[0, 0, 2]); + Assert.AreEqual(4, value.Array3D[0, 1, 0]); + Assert.AreEqual(5, value.Array3D[0, 1, 1]); + Assert.AreEqual(6, value.Array3D[0, 1, 2]); + } [Test] public void DeserializeByteArrayWithTypeName() diff --git a/Src/Newtonsoft.Json.Tests/TestObjects/HasByteArray.cs b/Src/Newtonsoft.Json.Tests/TestObjects/HasByteArray.cs index d9fd7d38..102bf70b 100644 --- a/Src/Newtonsoft.Json.Tests/TestObjects/HasByteArray.cs +++ b/Src/Newtonsoft.Json.Tests/TestObjects/HasByteArray.cs @@ -29,4 +29,10 @@ namespace Newtonsoft.Json.Tests.TestObjects { public byte[] EncryptedPassword { get; set; } } + + internal class HasMultidimensionalByteArray + { + public byte[,] Array2D { get; set; } + public byte[,,] Array3D { get; set; } + } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs index ad7d7a43..fd3cbaea 100644 --- a/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs @@ -187,7 +187,7 @@ namespace Newtonsoft.Json.Utilities // loop through the type name and filter out qualified assembly details from nested type names bool writingAssemblyName = false; bool skippingAssemblyDetails = false; - bool DimensionArrayMaybe = false; + bool followBrackets = false; for (int i = 0; i < fullyQualifiedTypeName.Length; i++) { char current = fullyQualifiedTypeName[i]; @@ -196,17 +196,17 @@ namespace Newtonsoft.Json.Utilities case '[': writingAssemblyName = false; skippingAssemblyDetails = false; - DimensionArrayMaybe = true; + followBrackets = true; builder.Append(current); break; case ']': writingAssemblyName = false; skippingAssemblyDetails = false; - DimensionArrayMaybe = false; + followBrackets = false; builder.Append(current); break; case ',': - if (DimensionArrayMaybe) + if (followBrackets) { builder.Append(current); } @@ -221,7 +221,7 @@ namespace Newtonsoft.Json.Utilities } break; default: - DimensionArrayMaybe = false; + followBrackets = false; if (!skippingAssemblyDetails) { builder.Append(current);