From 0e9241782e195d1bd28cb67e8faa7cba58530436 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Mon, 27 Jan 2020 23:46:37 +0300 Subject: [PATCH] Added opt-in flag to enable non-public members --- .../System.Text.Json/ref/System.Text.Json.cs | 1 + .../Text/Json/Serialization/JsonClassInfo.cs | 5 +++- .../Serialization/JsonSerializerOptions.cs | 21 ++++++++++++++++ .../Serialization/PropertyVisibilityTests.cs | 24 +++++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index c43f9c9a5f55cf..a823ce7c53204c 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -453,6 +453,7 @@ public sealed partial class JsonSerializerOptions { public JsonSerializerOptions() { } public bool AllowTrailingCommas { get { throw null; } set { } } + public bool AllowPrivateProperties { get { throw null; } set { } } public System.Collections.Generic.IList Converters { get { throw null; } } public int DefaultBufferSize { get { throw null; } set { } } public System.Text.Json.JsonNamingPolicy? DictionaryKeyPolicy { get { throw null; } set { } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs index dcc2a92e18dd15..8398a5a866416f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonClassInfo.cs @@ -138,7 +138,10 @@ public JsonClassInfo(Type type, JsonSerializerOptions options) { CreateObject = options.MemberAccessorStrategy.CreateConstructor(type); - PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + BindingFlags bindingFlags = options.AllowPrivateProperties + ? BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic + : BindingFlags.Instance | BindingFlags.Public; + PropertyInfo[] properties = type.GetProperties(bindingFlags); Dictionary cache = CreatePropertyCache(properties.Length); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs index 0e421917bc4401..ed4bfbc9c8a1eb 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs @@ -29,6 +29,7 @@ public sealed partial class JsonSerializerOptions private int _defaultBufferSize = BufferSizeDefault; private int _maxDepth; private bool _allowTrailingCommas; + private bool _allowPrivateProperties; private bool _haveTypesBeenCreated; private bool _ignoreNullValues; private bool _ignoreReadOnlyProperties; @@ -66,6 +67,26 @@ public bool AllowTrailingCommas } } + /// + /// Determines whether non-public properties should be serialized and deserialized. + /// The default value is false. + /// + /// + /// Thrown if this property is set after serialization or deserialization has occurred. + /// + public bool AllowPrivateProperties + { + get + { + return _allowPrivateProperties; + } + set + { + VerifyMutable(); + _allowPrivateProperties = value; + } + } + /// /// The default buffer size in bytes used when creating temporary buffers. /// diff --git a/src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.cs index cc9f383f26c4cf..869114fdadd768 100644 --- a/src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/Serialization/PropertyVisibilityTests.cs @@ -11,6 +11,30 @@ namespace System.Text.Json.Serialization.Tests { public static class PropertyVisibilityTests { + [Fact] + public static void Serialize_NonPublicProperty_RequiresOptIn() + { + var obj = new ClassWithPrivateProperty { PrivateProperty = true }; + var allowNonPublic = new JsonSerializerOptions { AllowPrivateProperties = true }; + + string jsonDefault = JsonSerializer.Serialize(obj); + string jsonNonPublic = JsonSerializer.Serialize(obj, allowNonPublic); + + Assert.Equal(@"{}", jsonDefault); + Assert.Equal(@"{""PrivateProperty"":true}", jsonNonPublic); + + var objDefault = JsonSerializer.Deserialize(jsonDefault); + var objNonPublic = JsonSerializer.Deserialize(jsonNonPublic, allowNonPublic); + + Assert.False(objDefault.PrivateProperty); + Assert.True(objNonPublic.PrivateProperty); + } + + public class ClassWithPrivateProperty + { + internal bool PrivateProperty { get; set; } + } + [Fact] public static void NoSetter() {