From 60a74cf2054d0c591299262f23b257b7c24eca6b Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Fri, 5 Jul 2024 22:30:41 +0800 Subject: [PATCH 1/5] feat: add new JsonIgnoreAttribute WhenWriting/WhenReading --- .../System.Text.Json/Common/JsonIgnoreCondition.cs | 10 ++++++++++ src/libraries/System.Text.Json/ref/System.Text.Json.cs | 2 ++ .../Json/Serialization/Metadata/JsonPropertyInfoOfT.cs | 8 ++++++++ 3 files changed, 20 insertions(+) diff --git a/src/libraries/System.Text.Json/Common/JsonIgnoreCondition.cs b/src/libraries/System.Text.Json/Common/JsonIgnoreCondition.cs index bea024fead644..e18c9507ae559 100644 --- a/src/libraries/System.Text.Json/Common/JsonIgnoreCondition.cs +++ b/src/libraries/System.Text.Json/Common/JsonIgnoreCondition.cs @@ -30,5 +30,15 @@ public enum JsonIgnoreCondition /// This is applied only to reference-type properties and fields. /// WhenWritingNull = 3, + + /// + /// Property is ignored during serialization + /// + WhenWriting = 4, + + /// + /// Property is ignored during deserialization + /// + WhenReading = 5, } } 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 110d60f1fb47d..2d6da7db3e8f8 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -1028,6 +1028,8 @@ public enum JsonIgnoreCondition Always = 1, WhenWritingDefault = 2, WhenWritingNull = 3, + WhenWriting = 4, + WhenReading = 5, } [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple=false)] public sealed partial class JsonIncludeAttribute : System.Text.Json.Serialization.JsonAttribute diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs index 1c62158aa85b7..8a55e22d45053 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs @@ -429,6 +429,14 @@ private protected override void ConfigureIgnoreCondition(JsonIgnoreCondition? ig IgnoreDefaultValuesOnWrite = true; break; + case JsonIgnoreCondition.WhenWriting: + ShouldSerialize = ShouldSerializeIgnoreConditionAlways; + break; + + case JsonIgnoreCondition.WhenReading: + Set = null; + break; + default: Debug.Fail($"Unknown value of JsonIgnoreCondition '{ignoreCondition}'"); break; From 9426328b204182357a7c94bff87e0e10e4d34d39 Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Tue, 16 Jul 2024 13:46:04 +0000 Subject: [PATCH 2/5] remove empty line to align existing style --- src/libraries/System.Text.Json/Common/JsonIgnoreCondition.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libraries/System.Text.Json/Common/JsonIgnoreCondition.cs b/src/libraries/System.Text.Json/Common/JsonIgnoreCondition.cs index e18c9507ae559..e2fb3b97307b8 100644 --- a/src/libraries/System.Text.Json/Common/JsonIgnoreCondition.cs +++ b/src/libraries/System.Text.Json/Common/JsonIgnoreCondition.cs @@ -30,12 +30,10 @@ public enum JsonIgnoreCondition /// This is applied only to reference-type properties and fields. /// WhenWritingNull = 3, - /// /// Property is ignored during serialization /// WhenWriting = 4, - /// /// Property is ignored during deserialization /// From 9fae8747c777150d6f0860ede4238cb20f33692a Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Mon, 22 Jul 2024 15:31:37 +0000 Subject: [PATCH 3/5] test: add test case --- .../tests/Common/PropertyVisibilityTests.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs index 010b6a580ed20..f4eca0041083c 100644 --- a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs @@ -2035,6 +2035,31 @@ public async Task JsonIgnoreCondition_LastOneWins() Assert.Null(obj.MyString); } + [Fact] + public void JsonIgnoreCondition_WhenWriting() + { + var json = JsonSerializer.Serialize(new JsonIgnoreCondition_WhenReadingWritingTestModel{ Age = 10, Name="Mike" }); + Assert.Equal("""{"Age":10}""", json); + } + + [Fact] + public void JsonIgnoreCondition_WhenReading() + { + var json = """{"Age":10, "Name":"Mike"}"""; + var model = JsonSerializer.Deserialize(json); + Assert.Equal("Mike", model.Name); + Assert.Equal(0, model.Age); + } + + public class JsonIgnoreCondition_WhenReadingWritingTestModel + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenReading)] + public int Age { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWriting)] + public string Name { get; set; } + } + + [Fact] public async Task ClassWithComplexObjectsUsingIgnoreWhenWritingDefaultAttribute() { From 54d3561e0473907061856362518d6d11dfe36b07 Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Mon, 22 Jul 2024 17:21:33 +0000 Subject: [PATCH 4/5] test: source generation test --- .../tests/Common/PropertyVisibilityTests.cs | 49 +++++++++---------- .../Serialization/PropertyVisibilityTests.cs | 2 + ...nTypeInfoResolverTests.JsonPropertyInfo.cs | 1 + 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs index f4eca0041083c..bd46878470d6d 100644 --- a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs @@ -2035,31 +2035,6 @@ public async Task JsonIgnoreCondition_LastOneWins() Assert.Null(obj.MyString); } - [Fact] - public void JsonIgnoreCondition_WhenWriting() - { - var json = JsonSerializer.Serialize(new JsonIgnoreCondition_WhenReadingWritingTestModel{ Age = 10, Name="Mike" }); - Assert.Equal("""{"Age":10}""", json); - } - - [Fact] - public void JsonIgnoreCondition_WhenReading() - { - var json = """{"Age":10, "Name":"Mike"}"""; - var model = JsonSerializer.Deserialize(json); - Assert.Equal("Mike", model.Name); - Assert.Equal(0, model.Age); - } - - public class JsonIgnoreCondition_WhenReadingWritingTestModel - { - [JsonIgnore(Condition = JsonIgnoreCondition.WhenReading)] - public int Age { get; set; } - [JsonIgnore(Condition = JsonIgnoreCondition.WhenWriting)] - public string Name { get; set; } - } - - [Fact] public async Task ClassWithComplexObjectsUsingIgnoreWhenWritingDefaultAttribute() { @@ -2190,6 +2165,30 @@ public async Task IgnoreConditionWhenWritingDefault_WinsOver_IgnoreReadOnlyField Assert.Equal(@"{}", json); } + [Fact] + public async Task JsonIgnoreCondition_WhenWriting() + { + var json = await Serializer.SerializeWrapper(new JsonIgnoreCondition_WhenReadingWritingTestModel{ Age = 10, Name = "Mike" }); + Assert.Equal("""{"Age":10}""", json); + } + + [Fact] + public async Task JsonIgnoreCondition_WhenReading() + { + var json = """{"Age":10, "Name":"Mike"}"""; + var model = await Serializer.DeserializeWrapper(json); + Assert.Equal("Mike", model.Name); + Assert.Equal(0, model.Age); + } + + public class JsonIgnoreCondition_WhenReadingWritingTestModel + { + [JsonIgnore(Condition = JsonIgnoreCondition.WhenReading)] + public int Age { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWriting)] + public string? Name { get; set; } + } + public class ClassWithReadOnlyStringProperty { public string MyString { get; } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs index 89635a6b64b5f..21b0792d84dda 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs @@ -340,6 +340,7 @@ public override async Task ClassWithIgnoredAndPrivateMembers_DoesNotIncludeIgnor [JsonSerializable(typeof(ClassWithProperty_IgnoreConditionAlways_Ctor))] [JsonSerializable(typeof(ClassWithClassProperty_IgnoreConditionWhenWritingDefault_Ctor))] [JsonSerializable(typeof(StructWithStructProperty_IgnoreConditionWhenWritingDefault_Ctor))] + [JsonSerializable(typeof(JsonIgnoreCondition_WhenReadingWritingTestModel))] [JsonSerializable(typeof(SmallStructWithValueAndReferenceTypes))] [JsonSerializable(typeof(WrapperForClassWithIgnoredUnsupportedDictionary))] [JsonSerializable(typeof(Class1))] @@ -613,6 +614,7 @@ partial class DefaultContextWithGlobalIgnoreSetting : JsonSerializerContext; [JsonSerializable(typeof(ClassWithProperty_IgnoreConditionAlways_Ctor))] [JsonSerializable(typeof(ClassWithClassProperty_IgnoreConditionWhenWritingDefault_Ctor))] [JsonSerializable(typeof(StructWithStructProperty_IgnoreConditionWhenWritingDefault_Ctor))] + [JsonSerializable(typeof(JsonIgnoreCondition_WhenReadingWritingTestModel))] [JsonSerializable(typeof(SmallStructWithValueAndReferenceTypes))] [JsonSerializable(typeof(WrapperForClassWithIgnoredUnsupportedDictionary))] [JsonSerializable(typeof(Class1))] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonPropertyInfo.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonPropertyInfo.cs index 631be65d8f24f..4f263a7c88289 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonPropertyInfo.cs @@ -908,6 +908,7 @@ public enum ModifyJsonIgnore [InlineData(JsonIgnoreCondition.Never, ModifyJsonIgnore.DontModify)] [InlineData(JsonIgnoreCondition.WhenWritingDefault, ModifyJsonIgnore.NeverSerialize)] [InlineData(JsonIgnoreCondition.WhenWritingNull, ModifyJsonIgnore.NeverSerialize)] + [InlineData(JsonIgnoreCondition.WhenWriting, ModifyJsonIgnore.NeverSerialize)] [InlineData(JsonIgnoreCondition.Never, ModifyJsonIgnore.NeverSerialize)] [InlineData(JsonIgnoreCondition.WhenWritingDefault, ModifyJsonIgnore.AlwaysSerialize)] [InlineData(JsonIgnoreCondition.WhenWritingNull, ModifyJsonIgnore.AlwaysSerialize)] From 87fc7b5e3cea15832d4f029f7d172ac5280e0f1e Mon Sep 17 00:00:00 2001 From: Weihan Li Date: Thu, 1 Aug 2024 00:53:47 +0800 Subject: [PATCH 5/5] update test case and fix some formatting --- .../tests/Common/PropertyVisibilityTests.cs | 9 +++++++-- .../Serialization/PropertyVisibilityTests.cs | 5 +++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs index bd46878470d6d..c619e5be4d0aa 100644 --- a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs @@ -2168,7 +2168,12 @@ public async Task IgnoreConditionWhenWritingDefault_WinsOver_IgnoreReadOnlyField [Fact] public async Task JsonIgnoreCondition_WhenWriting() { - var json = await Serializer.SerializeWrapper(new JsonIgnoreCondition_WhenReadingWritingTestModel{ Age = 10, Name = "Mike" }); + var options = new JsonSerializerOptions { IgnoreReadOnlyProperties = true }; + var json = await Serializer.SerializeWrapper + ( + new JsonIgnoreCondition_WhenReadingWritingTestModel { Age = 10, Name = "Mike" }, + options + ); Assert.Equal("""{"Age":10}""", json); } @@ -2182,7 +2187,7 @@ public async Task JsonIgnoreCondition_WhenReading() } public class JsonIgnoreCondition_WhenReadingWritingTestModel - { + { [JsonIgnore(Condition = JsonIgnoreCondition.WhenReading)] public int Age { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWriting)] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs index 21b0792d84dda..21f220509ad36 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs @@ -129,7 +129,7 @@ public override async Task HonorJsonPropertyName_PrivateGetter() Assert.Equal(MySmallEnum.AnotherValue, obj.GetProxy()); // JsonInclude for private members not supported in source gen - await Assert.ThrowsAsync(async() => await Serializer.SerializeWrapper(obj)); + await Assert.ThrowsAsync(async () => await Serializer.SerializeWrapper(obj)); } [Fact] @@ -331,7 +331,8 @@ public override async Task ClassWithIgnoredAndPrivateMembers_DoesNotIncludeIgnor [JsonSerializable(typeof(IDiamondInterfaceHierarchyWithNamingConflict.IJoinInterface), TypeInfoPropertyName = "IDiamondInterfaceHierarchyWithNamingConflictIJoinInterface")] [JsonSerializable(typeof(IDiamondInterfaceHierarchyWithNamingConflictUsingAttribute.IJoinInterface), TypeInfoPropertyName = "IDiamondInterfaceHierarchyWithNamingConflictUsingAttributeIJoinInterface")] [JsonSerializable(typeof(CollectionWithPrivateElementType))] - [JsonSerializable(typeof(DictionaryWithPrivateKeyAndValueType))][JsonSerializable(typeof(ClassWithIgnoredAndPrivateMembers))] + [JsonSerializable(typeof(DictionaryWithPrivateKeyAndValueType))] + [JsonSerializable(typeof(ClassWithIgnoredAndPrivateMembers))] [JsonSerializable(typeof(ClassWithInternalJsonIncludeProperties))] [JsonSerializable(typeof(ClassWithIgnoredAndPrivateMembers))] [JsonSerializable(typeof(ClassUsingIgnoreWhenWritingDefaultAttribute))]