From 4e76f0d6a3a0a7d1a5b710ae03ad64ba60465ece Mon Sep 17 00:00:00 2001 From: Sychev Vadim Date: Fri, 5 Feb 2021 14:38:19 +0300 Subject: [PATCH 1/3] New test that JsonIncludeAttribute is honored during deserialization ArgumentDeserialization_Honors_JsonInclude test is added #47855 --- .../ConstructorTests.ParameterMatching.cs | 13 +++++++++++ .../ConstructorTests.Stream.cs | 9 ++++---- .../TestClasses/TestClasses.Constructor.cs | 22 +++++++++++++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs index ac6718a447eece..4806bb3e80a2d4 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs @@ -834,6 +834,19 @@ public async Task HonorExtensionDataGeneric() Assert.Equal("value", ((JsonElement)obj4.ExtensionData["key"]).GetString()); } + [Fact] + public async Task ArgumentDeserialization_Honors_JsonInclude() + { + Point_MembersHave_JsonInclude point = new Point_MembersHave_JsonInclude(1, 2); + + string json = JsonSerializer.Serialize(point); + Assert.Contains(@"""X"":1", json); + Assert.Contains(@"""Y"":2", json); + + point = await Serializer.DeserializeWrapper(json); + point.Verify(); + } + [Fact] public async Task ArgumentDeserialization_Honors_JsonPropertyName() { diff --git a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.Stream.cs b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.Stream.cs index e89ec547da70b8..1028c5146a1723 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.Stream.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.Stream.cs @@ -29,7 +29,7 @@ async Task RunTestAsync(byte[] testData) } // Array size is the count of the following tests. - Task[] tasks = new Task[14]; + Task[] tasks = new Task[15]; // Simple models can be deserialized. tasks[0] = Task.Run(async () => await RunTestAsync(Parameterized_IndexViewModel_Immutable.s_data)); @@ -48,10 +48,11 @@ async Task RunTestAsync(byte[] testData) tasks[8] = Task.Run(async () => await RunTestAsync(Point_MembersHave_JsonPropertyName.s_data)); tasks[9] = Task.Run(async () => await RunTestAsync(Point_MembersHave_JsonConverter.s_data)); tasks[10] = Task.Run(async () => await RunTestAsync(Point_MembersHave_JsonIgnore.s_data)); + tasks[11] = Task.Run(async () => await RunTestAsync(Point_MembersHave_JsonInclude.s_data)); // Complex JSON as last argument works - tasks[11] = Task.Run(async () => await RunTestAsync(Point_With_Array.s_data)); - tasks[12] = Task.Run(async () => await RunTestAsync(Point_With_Dictionary.s_data)); - tasks[13] = Task.Run(async () => await RunTestAsync(Point_With_Object.s_data)); + tasks[12] = Task.Run(async () => await RunTestAsync(Point_With_Array.s_data)); + tasks[13] = Task.Run(async () => await RunTestAsync(Point_With_Dictionary.s_data)); + tasks[14] = Task.Run(async () => await RunTestAsync(Point_With_Object.s_data)); await Task.WhenAll(tasks); } diff --git a/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs b/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs index 8dcd74e79dfb3b..459aad3abb93bc 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs @@ -2060,6 +2060,28 @@ public void Verify() } } + public class Point_MembersHave_JsonInclude : ITestClass + { + [JsonInclude] + public int X { get; } + + [JsonInclude] + public int Y { get; } + + public Point_MembersHave_JsonInclude(int x, int y) => (X, Y) = (x, y); + + public void Initialize() { } + + public static readonly string s_json = @"{""X"":1,""Y"":2}"; + + public static readonly byte[] s_data = Encoding.UTF8.GetBytes(s_json); + public void Verify() + { + Assert.Equal(1, X); + Assert.Equal(2, Y); + } + } + public class Point_MultipleMembers_BindTo_OneConstructorParameter { public int X { get; } From 3d2f081fceea7e46f8520e6a554f004031c107a1 Mon Sep 17 00:00:00 2001 From: Sychev Vadim Date: Fri, 5 Feb 2021 15:37:28 +0300 Subject: [PATCH 2/3] New test that JsonNumberHandlingAttribute is honored during deserialization ArgumentDeserialization_Honors_JsonNumberHandling test is added #47855 --- .../ConstructorTests.ParameterMatching.cs | 14 ++++++++ .../ConstructorTests.Stream.cs | 9 ++--- .../TestClasses/TestClasses.Constructor.cs | 35 ++++++++++++++++++- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs index 4806bb3e80a2d4..1c34c0c3c4492f 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs @@ -847,6 +847,20 @@ public async Task ArgumentDeserialization_Honors_JsonInclude() point.Verify(); } + [Fact] + public async Task ArgumentDeserialization_Honors_JsonNumberHandling() + { + ClassWithFiveArgs_MembersHave_JsonNumberHandlingAttributes obj = await Serializer.DeserializeWrapper(ClassWithFiveArgs_MembersHave_JsonNumberHandlingAttributes.s_json); + obj.Verify(); + + string json = JsonSerializer.Serialize(obj); + Assert.Contains(@"""A"":1", json); + Assert.Contains(@"""B"":""NaN""", json); + Assert.Contains(@"""C"":2", json); + Assert.Contains(@"""D"":""3""", json); + Assert.Contains(@"""E"":""4""", json); + } + [Fact] public async Task ArgumentDeserialization_Honors_JsonPropertyName() { diff --git a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.Stream.cs b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.Stream.cs index 1028c5146a1723..8f0f166012947c 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.Stream.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.Stream.cs @@ -29,7 +29,7 @@ async Task RunTestAsync(byte[] testData) } // Array size is the count of the following tests. - Task[] tasks = new Task[15]; + Task[] tasks = new Task[16]; // Simple models can be deserialized. tasks[0] = Task.Run(async () => await RunTestAsync(Parameterized_IndexViewModel_Immutable.s_data)); @@ -49,10 +49,11 @@ async Task RunTestAsync(byte[] testData) tasks[9] = Task.Run(async () => await RunTestAsync(Point_MembersHave_JsonConverter.s_data)); tasks[10] = Task.Run(async () => await RunTestAsync(Point_MembersHave_JsonIgnore.s_data)); tasks[11] = Task.Run(async () => await RunTestAsync(Point_MembersHave_JsonInclude.s_data)); + tasks[12] = Task.Run(async () => await RunTestAsync(ClassWithFiveArgs_MembersHave_JsonNumberHandlingAttributes.s_data)); // Complex JSON as last argument works - tasks[12] = Task.Run(async () => await RunTestAsync(Point_With_Array.s_data)); - tasks[13] = Task.Run(async () => await RunTestAsync(Point_With_Dictionary.s_data)); - tasks[14] = Task.Run(async () => await RunTestAsync(Point_With_Object.s_data)); + tasks[13] = Task.Run(async () => await RunTestAsync(Point_With_Array.s_data)); + tasks[14] = Task.Run(async () => await RunTestAsync(Point_With_Dictionary.s_data)); + tasks[15] = Task.Run(async () => await RunTestAsync(Point_With_Object.s_data)); await Task.WhenAll(tasks); } diff --git a/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs b/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs index 459aad3abb93bc..9e1e9621d4009b 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs @@ -2059,7 +2059,7 @@ public void Verify() Assert.Equal(0, Y); // We don't set parameter default value here. } } - + public class Point_MembersHave_JsonInclude : ITestClass { [JsonInclude] @@ -2082,6 +2082,39 @@ public void Verify() } } + public class ClassWithFiveArgs_MembersHave_JsonNumberHandlingAttributes : ITestClass + { + [JsonNumberHandling(JsonNumberHandling.Strict)] + public int A { get; } + + [JsonNumberHandling(JsonNumberHandling.AllowNamedFloatingPointLiterals)] + public float B { get; } + + [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)] + public int C { get; } + + [JsonNumberHandling(JsonNumberHandling.WriteAsString)] + public int D { get; } + + [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)] + public int E { get; } + + public ClassWithFiveArgs_MembersHave_JsonNumberHandlingAttributes(int a, float b, int c, int d, int e) => (A, B, C, D, E) = (a, b, c, d, e); + public void Initialize() { } + + public static readonly string s_json = @"{""A"":1,""B"":""NaN"",""C"":""2"",""D"": 3,""E"":""4""}"; + + public static readonly byte[] s_data = Encoding.UTF8.GetBytes(s_json); + public void Verify() + { + Assert.Equal(1, A); + Assert.Equal(float.NaN, B); + Assert.Equal(2, C); + Assert.Equal(3, D); + Assert.Equal(4, E); + } + } + public class Point_MultipleMembers_BindTo_OneConstructorParameter { public int X { get; } From fe6b29ddd7cd0e7fa5cf2d21df9f309aaa3a911c Mon Sep 17 00:00:00 2001 From: Sychev Vadim Date: Sun, 7 Feb 2021 13:58:55 +0300 Subject: [PATCH 3/3] Extended Point_MembersHave_JsonInclude class for variety of test cases Added new lines --- .../ConstructorTests.ParameterMatching.cs | 5 ++++- .../TestClasses/TestClasses.Constructor.cs | 12 +++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs index 1c34c0c3c4492f..ae8da63d622d0a 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/ConstructorTests/ConstructorTests.ParameterMatching.cs @@ -837,11 +837,14 @@ public async Task HonorExtensionDataGeneric() [Fact] public async Task ArgumentDeserialization_Honors_JsonInclude() { - Point_MembersHave_JsonInclude point = new Point_MembersHave_JsonInclude(1, 2); + Point_MembersHave_JsonInclude point = new Point_MembersHave_JsonInclude(1, 2,3); string json = JsonSerializer.Serialize(point); Assert.Contains(@"""X"":1", json); Assert.Contains(@"""Y"":2", json); + //We should add another test for non-public members + //when https://github.com/dotnet/runtime/issues/31511 is implemented + Assert.Contains(@"""Z"":3", json); point = await Serializer.DeserializeWrapper(json); point.Verify(); diff --git a/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs b/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs index 9e1e9621d4009b..e4d25ea36926c5 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/TestClasses/TestClasses.Constructor.cs @@ -2066,19 +2066,23 @@ public class Point_MembersHave_JsonInclude : ITestClass public int X { get; } [JsonInclude] - public int Y { get; } + public int Y { get; private set; } + + public int Z { get; private set; } - public Point_MembersHave_JsonInclude(int x, int y) => (X, Y) = (x, y); + public Point_MembersHave_JsonInclude(int x, int y, int z) => (X, Y, Z) = (x, y, z); public void Initialize() { } - public static readonly string s_json = @"{""X"":1,""Y"":2}"; + public static readonly string s_json = @"{""X"":1,""Y"":2,""Z"":3}"; public static readonly byte[] s_data = Encoding.UTF8.GetBytes(s_json); + public void Verify() { Assert.Equal(1, X); Assert.Equal(2, Y); + Assert.Equal(3, Z); } } @@ -2100,11 +2104,13 @@ public class ClassWithFiveArgs_MembersHave_JsonNumberHandlingAttributes : ITestC public int E { get; } public ClassWithFiveArgs_MembersHave_JsonNumberHandlingAttributes(int a, float b, int c, int d, int e) => (A, B, C, D, E) = (a, b, c, d, e); + public void Initialize() { } public static readonly string s_json = @"{""A"":1,""B"":""NaN"",""C"":""2"",""D"": 3,""E"":""4""}"; public static readonly byte[] s_data = Encoding.UTF8.GetBytes(s_json); + public void Verify() { Assert.Equal(1, A);