diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs index 4339851dce17cb..97d0c0849909cf 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs @@ -1514,6 +1514,11 @@ private void ProcessMember( continue; } + if (property.DefaultIgnoreCondition == JsonIgnoreCondition.Always && !property.IsRequired) + { + continue; + } + if ((property.IsRequired && !constructorSetsRequiredMembers) || property.IsInitOnlySetter) { if (!(memberInitializerNames ??= new()).Add(property.MemberName)) diff --git a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.InitOnly.cs b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.InitOnly.cs index a0547a4bf55ff9..285b199ab71631 100644 --- a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.InitOnly.cs +++ b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.InitOnly.cs @@ -64,6 +64,29 @@ public virtual async Task NonPublicInitOnlySetter_With_JsonInclude(Type type) Assert.Equal(@"{""MyInt"":1}", await Serializer.SerializeWrapper(obj)); } + [Theory] + [InlineData(typeof(Class_WithIgnoredInitOnlyProperty_WithDefaultValue))] + [InlineData(typeof(Record_WithIgnoredPropertyInCtor_WithDefaultValue))] + public async Task InitOnlySetter_With_JsonIgnoreAlways_AndWith_DefaultValue(Type type) + { + object obj = await Serializer.DeserializeWrapper(@"{""MyInt"":1}", type); + Assert.Equal(42, (int)type.GetProperty("MyInt").GetValue(obj)); + } + + [Fact] + public async Task JsonIgnoreOnInitOnlyProperty() + { + // Regression test for https://github.com/dotnet/runtime/issues/101877 + + RecordWithIgnoredNestedInitOnlyProperty.InnerRecord inner = new(42, "Baz"); + RecordWithIgnoredNestedInitOnlyProperty value = new RecordWithIgnoredNestedInitOnlyProperty(inner); + string json = await Serializer.SerializeWrapper(value); + Assert.Equal("""{"foo":42}""", json); + + RecordWithIgnoredNestedInitOnlyProperty? deserializedValue = await Serializer.DeserializeWrapper(json); + Assert.Equal(value, deserializedValue); + } + [Fact] public async Task NullableStructWithInitOnlyProperty() { @@ -132,5 +155,28 @@ public class Class_PropertyWith_ProtectedInitOnlySetter_WithAttribute [JsonInclude] public int MyInt { get; protected init; } } + + public class Class_WithIgnoredInitOnlyProperty_WithDefaultValue + { + [JsonIgnore(Condition = JsonIgnoreCondition.Always)] + public int MyInt { get; init; } = 42; + } + + public record Record_WithIgnoredPropertyInCtor_WithDefaultValue( + [property: JsonIgnore] int MyInt = 42); + + public record RecordWithIgnoredNestedInitOnlyProperty( + [property: JsonIgnore] RecordWithIgnoredNestedInitOnlyProperty.InnerRecord Other) + { + [JsonConstructor] + public RecordWithIgnoredNestedInitOnlyProperty(int foo) + : this(new InnerRecord(foo, "Baz")) + { + } + + [JsonPropertyName("foo")] public int Foo => Other.Foo; + + public record InnerRecord(int Foo, string Bar); + } } } 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 21f220509ad360..bce43700c2548d 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 @@ -198,6 +198,9 @@ public override async Task ClassWithIgnoredAndPrivateMembers_DoesNotIncludeIgnor [JsonSerializable(typeof(ClassWithStructProperty_IgnoreConditionWhenWritingDefault))] [JsonSerializable(typeof(ClassWithMissingObjectProperty))] [JsonSerializable(typeof(ClassWithInitOnlyProperty))] + [JsonSerializable(typeof(Class_WithIgnoredInitOnlyProperty_WithDefaultValue))] + [JsonSerializable(typeof(Record_WithIgnoredPropertyInCtor_WithDefaultValue))] + [JsonSerializable(typeof(RecordWithIgnoredNestedInitOnlyProperty))] [JsonSerializable(typeof(StructWithInitOnlyProperty))] [JsonSerializable(typeof(StructWithInitOnlyProperty?))] [JsonSerializable(typeof(ClassWithCustomNamedInitOnlyProperty))] @@ -473,6 +476,9 @@ partial class DefaultContextWithGlobalIgnoreSetting : JsonSerializerContext; [JsonSerializable(typeof(ClassWithStructProperty_IgnoreConditionWhenWritingDefault))] [JsonSerializable(typeof(ClassWithMissingObjectProperty))] [JsonSerializable(typeof(ClassWithInitOnlyProperty))] + [JsonSerializable(typeof(Class_WithIgnoredInitOnlyProperty_WithDefaultValue))] + [JsonSerializable(typeof(Record_WithIgnoredPropertyInCtor_WithDefaultValue))] + [JsonSerializable(typeof(RecordWithIgnoredNestedInitOnlyProperty))] [JsonSerializable(typeof(StructWithInitOnlyProperty))] [JsonSerializable(typeof(StructWithInitOnlyProperty?))] [JsonSerializable(typeof(ClassWithCustomNamedInitOnlyProperty))]