Skip to content

Commit 8e2b607

Browse files
[release/6.0] Treat 'abstract' properties the same as 'virtual' for src-gen (#59771)
* Treat 'abstract' properties the same as 'virtual' for src-gen * Change virtual detection; move test to common Co-authored-by: Steve Harter <[email protected]>
1 parent 9f66ef7 commit 8e2b607

File tree

3 files changed

+92
-1
lines changed

3 files changed

+92
-1
lines changed

src/libraries/System.Text.Json/gen/Reflection/RoslynExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public static MethodAttributes GetMethodAttributes(this IMethodSymbol methodSymb
3737

3838
if (methodSymbol.IsAbstract)
3939
{
40-
attributes |= MethodAttributes.Abstract;
40+
attributes |= MethodAttributes.Abstract | MethodAttributes.Virtual;
4141
}
4242

4343
if (methodSymbol.IsStatic)

src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2653,5 +2653,94 @@ public async Task JsonIgnoreCondition_WhenWritingDefault_OnInterface()
26532653
json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
26542654
Assert.Equal("{\"MyProp\":{}}", json);
26552655
}
2656+
2657+
public class ConcreteDerivedClass : AbstractBaseClass
2658+
{
2659+
// Ignored including on base class:
2660+
[JsonIgnore] public override int Abstract_Ignored_Property { get; set; }
2661+
[JsonIgnore] public override int Virtual_Ignored_Property { get; set; }
2662+
2663+
// Ignored but not specified on base class:
2664+
[JsonIgnore] public override int Abstract_IgnoredOnConcrete_Property { get; set; }
2665+
[JsonIgnore] public override int Virtual_IgnoredOnConcrete_Property { get; set; }
2666+
2667+
// Ignored specified on base class:
2668+
[JsonPropertyOrder(1)] public override int Abstract_IgnoredOnBase_Property { get; set; }
2669+
[JsonPropertyOrder(2)] public override int Virtual_IgnoredOnBase_Property { get; set; }
2670+
2671+
// Standard overrides (not ignored):
2672+
[JsonPropertyOrder(3)] public override int Abstract_Property { get; set; }
2673+
[JsonPropertyOrder(4)] public override int Virtual_Property { get; set; }
2674+
}
2675+
2676+
public abstract class AbstractBaseClass
2677+
{
2678+
[JsonIgnore] public abstract int Abstract_Ignored_Property { get; set; }
2679+
[JsonIgnore] public virtual int Virtual_Ignored_Property { get; set; }
2680+
2681+
public abstract int Abstract_IgnoredOnConcrete_Property { get; set; }
2682+
public virtual int Virtual_IgnoredOnConcrete_Property { get; set; }
2683+
2684+
[JsonIgnore] public abstract int Abstract_IgnoredOnBase_Property { get; set; }
2685+
[JsonIgnore] public virtual int Virtual_IgnoredOnBase_Property { get; set; }
2686+
2687+
public abstract int Abstract_Property { get; set; }
2688+
public virtual int Virtual_Property { get; set; }
2689+
}
2690+
2691+
[Fact]
2692+
public async Task JsonIgnoreCondition_Polymorphic()
2693+
{
2694+
ConcreteDerivedClass obj = new()
2695+
{
2696+
Abstract_Ignored_Property = -1,
2697+
Virtual_Ignored_Property = -1,
2698+
Abstract_IgnoredOnConcrete_Property = -1,
2699+
Virtual_IgnoredOnConcrete_Property = -1,
2700+
Abstract_IgnoredOnBase_Property = 1,
2701+
Virtual_IgnoredOnBase_Property = 2,
2702+
Abstract_Property = 3,
2703+
Virtual_Property = 4,
2704+
};
2705+
2706+
// Verify properties work as expected.
2707+
Assert.Equal(-1, obj.Abstract_Ignored_Property);
2708+
Assert.Equal(-1, obj.Virtual_Ignored_Property);
2709+
Assert.Equal(-1, obj.Abstract_IgnoredOnConcrete_Property);
2710+
Assert.Equal(-1, obj.Virtual_IgnoredOnConcrete_Property);
2711+
Assert.Equal(1, obj.Abstract_IgnoredOnBase_Property);
2712+
Assert.Equal(2, obj.Virtual_IgnoredOnBase_Property);
2713+
Assert.Equal(3, obj.Abstract_Property);
2714+
Assert.Equal(4, obj.Virtual_Property);
2715+
2716+
const string ExpectedJson = "{" +
2717+
"\"Abstract_IgnoredOnBase_Property\":1," +
2718+
"\"Virtual_IgnoredOnBase_Property\":2," +
2719+
"\"Abstract_Property\":3," +
2720+
"\"Virtual_Property\":4}";
2721+
2722+
string json = await JsonSerializerWrapperForString.SerializeWrapper(obj);
2723+
Assert.Equal(ExpectedJson, json);
2724+
2725+
const string Json = "{" +
2726+
"\"Abstract_Ignored_Property\":-1," +
2727+
"\"Virtual_Ignored_Property\":-1," +
2728+
"\"Abstract_IgnoredOnConcrete_Property\":-1," +
2729+
"\"Virtual_IgnoredOnConcrete_Property\":-1," +
2730+
"\"Abstract_IgnoredOnBase_Property\":1," +
2731+
"\"Virtual_IgnoredOnBase_Property\":2," +
2732+
"\"Abstract_Property\":3," +
2733+
"\"Virtual_Property\":4}";
2734+
2735+
obj = await JsonSerializerWrapperForString.DeserializeWrapper<ConcreteDerivedClass>(Json);
2736+
Assert.Equal(0, obj.Abstract_Ignored_Property);
2737+
Assert.Equal(0, obj.Virtual_Ignored_Property);
2738+
Assert.Equal(0, obj.Abstract_IgnoredOnConcrete_Property);
2739+
Assert.Equal(0, obj.Virtual_IgnoredOnConcrete_Property);
2740+
Assert.Equal(1, obj.Abstract_IgnoredOnBase_Property);
2741+
Assert.Equal(2, obj.Virtual_IgnoredOnBase_Property);
2742+
Assert.Equal(3, obj.Abstract_Property);
2743+
Assert.Equal(4, obj.Virtual_Property);
2744+
}
26562745
}
26572746
}

src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ public override async Task HonorJsonPropertyName_PrivateSetter()
263263
[JsonSerializable(typeof(StructWithPropertiesWithJsonPropertyName_PrivateSetter))]
264264
[JsonSerializable(typeof(ClassWithValueAndReferenceTypes))]
265265
[JsonSerializable(typeof(ClassWithReadOnlyStringProperty_IgnoreWhenWritingDefault))]
266+
[JsonSerializable(typeof(ConcreteDerivedClass))]
266267
internal sealed partial class PropertyVisibilityTestsContext_Metadata : JsonSerializerContext
267268
{
268269
}
@@ -429,6 +430,7 @@ public override async Task JsonIgnoreCondition_WhenWritingNull_OnValueType_Fail_
429430
[JsonSerializable(typeof(StructWithPropertiesWithJsonPropertyName_PrivateSetter))]
430431
[JsonSerializable(typeof(ClassWithValueAndReferenceTypes))]
431432
[JsonSerializable(typeof(ClassWithReadOnlyStringProperty_IgnoreWhenWritingDefault))]
433+
[JsonSerializable(typeof(ConcreteDerivedClass))]
432434
internal sealed partial class PropertyVisibilityTestsContext_Default : JsonSerializerContext
433435
{
434436
}

0 commit comments

Comments
 (0)