Verify JsonSerializer support for init-only properties (#40150)
authorLayomi Akinrinade <laakinri@microsoft.com>
Thu, 30 Jul 2020 21:52:15 +0000 (14:52 -0700)
committerGitHub <noreply@github.com>
Thu, 30 Jul 2020 21:52:15 +0000 (14:52 -0700)
src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.NonPublicAccessors.cs
src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.cs
src/libraries/System.Text.Json/tests/Serialization/PropertyVisiblityTests.InitOnly.cs [new file with mode: 0644]
src/libraries/System.Text.Json/tests/System.Text.Json.Tests.csproj

index be76b5e..0dd3657 100644 (file)
@@ -298,6 +298,9 @@ namespace System.Text.Json.Serialization.Tests
         [InlineData(typeof(ClassWithPrivateField_WithJsonIncludeProperty))]
         [InlineData(typeof(ClassWithInternalField_WithJsonIncludeProperty))]
         [InlineData(typeof(ClassWithProtectedField_WithJsonIncludeProperty))]
+        [InlineData(typeof(ClassWithPrivate_InitOnlyProperty_WithJsonIncludeProperty))]
+        [InlineData(typeof(ClassWithInternal_InitOnlyProperty_WithJsonIncludeProperty))]
+        [InlineData(typeof(ClassWithProtected_InitOnlyProperty_WithJsonIncludeProperty))]
         public static void NonPublicProperty_WithJsonInclude_Invalid(Type type)
         {
             InvalidOperationException ex = Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize("", type));
@@ -350,5 +353,23 @@ namespace System.Text.Json.Serialization.Tests
             [JsonInclude]
             protected string MyString = null;
         }
+
+        private class ClassWithPrivate_InitOnlyProperty_WithJsonIncludeProperty
+        {
+            [JsonInclude]
+            private string MyString { get; init; }
+        }
+
+        private class ClassWithInternal_InitOnlyProperty_WithJsonIncludeProperty
+        {
+            [JsonInclude]
+            internal string MyString { get; init; }
+        }
+
+        private class ClassWithProtected_InitOnlyProperty_WithJsonIncludeProperty
+        {
+            [JsonInclude]
+            protected string MyString { get; init; }
+        }
     }
 }
index 6e377f8..0628133 100644 (file)
@@ -3,8 +3,8 @@
 
 using System.Collections.Generic;
 using System.Collections.Concurrent;
-using Xunit;
 using System.Numerics;
+using Xunit;
 
 namespace System.Text.Json.Serialization.Tests
 {
diff --git a/src/libraries/System.Text.Json/tests/Serialization/PropertyVisiblityTests.InitOnly.cs b/src/libraries/System.Text.Json/tests/Serialization/PropertyVisiblityTests.InitOnly.cs
new file mode 100644 (file)
index 0000000..48fe1e3
--- /dev/null
@@ -0,0 +1,94 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Xunit;
+
+namespace System.Text.Json.Serialization.Tests
+{
+    public static partial class PropertyVisibilityTests
+    {
+        [Theory]
+        [InlineData(typeof(ClassWithInitOnlyProperty))]
+        [InlineData(typeof(StructWithInitOnlyProperty))]
+        public static void InitOnlyProperties_Work(Type type)
+        {
+            // Init-only property included by default.
+            object obj = JsonSerializer.Deserialize(@"{""MyInt"":1}", type);
+            Assert.Equal(1, (int)type.GetProperty("MyInt").GetValue(obj));
+
+            // Init-only properties can be serialized.
+            Assert.Equal(@"{""MyInt"":1}", JsonSerializer.Serialize(obj));
+        }
+
+        [Theory]
+        [InlineData(typeof(Class_PropertyWith_PrivateInitOnlySetter))]
+        [InlineData(typeof(Class_PropertyWith_InternalInitOnlySetter))]
+        [InlineData(typeof(Class_PropertyWith_ProtectedInitOnlySetter))]
+        public static void NonPublicInitOnlySetter_Without_JsonInclude_Fails(Type type)
+        {
+            // Non-public init-only property setter ignored.
+            object obj = JsonSerializer.Deserialize(@"{""MyInt"":1}", type);
+            Assert.Equal(0, (int)type.GetProperty("MyInt").GetValue(obj));
+
+            // Public getter can be used for serialization.
+            Assert.Equal(@"{""MyInt"":0}", JsonSerializer.Serialize(obj));
+        }
+
+        [Theory]
+        [InlineData(typeof(Class_PropertyWith_PrivateInitOnlySetter_WithAttribute))]
+        [InlineData(typeof(Class_PropertyWith_InternalInitOnlySetter_WithAttribute))]
+        [InlineData(typeof(Class_PropertyWith_ProtectedInitOnlySetter_WithAttribute))]
+        public static void NonPublicInitOnlySetter_With_JsonInclude_Works(Type type)
+        {
+            // Non-public init-only property setter included with [JsonInclude].
+            object obj = JsonSerializer.Deserialize(@"{""MyInt"":1}", type);
+            Assert.Equal(1, (int)type.GetProperty("MyInt").GetValue(obj));
+
+            // Init-only properties can be serialized.
+            Assert.Equal(@"{""MyInt"":1}", JsonSerializer.Serialize(obj));
+        }
+
+        public class ClassWithInitOnlyProperty
+        {
+            public int MyInt { get; init; }
+        }
+
+        public struct StructWithInitOnlyProperty
+        {
+            public int MyInt { get; init; }
+        }
+
+        public class Class_PropertyWith_PrivateInitOnlySetter
+        {
+            public int MyInt { get; private init; }
+        }
+
+        public class Class_PropertyWith_InternalInitOnlySetter
+        {
+            public int MyInt { get; internal init; }
+        }
+
+        public class Class_PropertyWith_ProtectedInitOnlySetter
+        {
+            public int MyInt { get; protected init; }
+        }
+
+        public class Class_PropertyWith_PrivateInitOnlySetter_WithAttribute
+        {
+            [JsonInclude]
+            public int MyInt { get; private init; }
+        }
+
+        public class Class_PropertyWith_InternalInitOnlySetter_WithAttribute
+        {
+            [JsonInclude]
+            public int MyInt { get; internal init; }
+        }
+
+        public class Class_PropertyWith_ProtectedInitOnlySetter_WithAttribute
+        {
+            [JsonInclude]
+            public int MyInt { get; protected init; }
+        }
+    }
+}
index 808880d..74459b8 100644 (file)
@@ -99,6 +99,7 @@
     <Compile Include="Serialization\OptionsTests.cs" />
     <Compile Include="Serialization\PolymorphicTests.cs" />
     <Compile Include="Serialization\PropertyNameTests.cs" />
+    <Compile Include="Serialization\PropertyVisiblityTests.InitOnly.cs" />
     <Compile Include="Serialization\PropertyVisibilityTests.NonPublicAccessors.cs" />
     <Compile Include="Serialization\PropertyVisibilityTests.cs" />
     <Compile Include="Serialization\ReadScenarioTests.cs" />