diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/TypeInfoResolverFunctionalTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/TypeInfoResolverFunctionalTests.cs index b80719e7c68b3..ebece0937fa46 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/TypeInfoResolverFunctionalTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/TypeInfoResolverFunctionalTests.cs @@ -545,7 +545,7 @@ public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions option if (jsonTypeInfo.Kind == JsonTypeInfoKind.Object && type.GetCustomAttribute() is not null) { - jsonTypeInfo.Properties.Clear(); + jsonTypeInfo.Properties.Clear(); // TODO should not require clearing IEnumerable<(PropertyInfo propInfo, DataMemberAttribute attr)> properties = type .GetProperties(BindingFlags.Instance | BindingFlags.Public) @@ -621,6 +621,64 @@ public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions option } } + [Fact] + public static void FieldContractResolverScenario() + { + var options = new JsonSerializerOptions { TypeInfoResolver = new FieldContractResolver() }; + + var value = FieldContractResolver.TestClass.Create("str", 42, true); + string json = JsonSerializer.Serialize(value, options); + Assert.Equal("""{"_string":"str","_int":42,"_bool":true}""", json); + + FieldContractResolver.TestClass result = JsonSerializer.Deserialize(json, options); + Assert.Equal(value, result); + } + + internal class FieldContractResolver : DefaultJsonTypeInfoResolver + { + public class TestClass + { + private string _string; + private int _int; + private bool _bool; + + public static TestClass Create(string @string, int @int, bool @bool) + => new TestClass { _string = @string, _int = @int, _bool = @bool }; + + // Should be ignored by the serializer + public bool Boolean + { + get => _bool; + set => throw new NotSupportedException(); + } + + public override int GetHashCode() => (_string, _int, _bool).GetHashCode(); + public override bool Equals(object? other) + => other is TestClass tc && (_string, _int, _bool) == (tc._string, tc._int, tc._bool); + } + + public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options) + { + JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options); + + if (jsonTypeInfo.Kind == JsonTypeInfoKind.Object) + { + jsonTypeInfo.Properties.Clear(); + + foreach (FieldInfo field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + { + JsonPropertyInfo jsonPropertyInfo = jsonTypeInfo.CreateJsonPropertyInfo(field.FieldType, field.Name); + jsonPropertyInfo.Get = field.GetValue; + jsonPropertyInfo.Set = field.SetValue; + + jsonTypeInfo.Properties.Add(jsonPropertyInfo); + } + } + + return jsonTypeInfo; + } + } + internal class TestClass { public int TestProperty { get; set; }