From c0a79f8126d5a120c29ece7fa0af4f33f5b5138a Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Wed, 23 Apr 2025 18:55:57 +0300 Subject: [PATCH] Account for CompilationMappingAttribute supporting multiple declarations. --- .../Metadata/FSharpCoreReflectionProxy.cs | 7 +++++-- .../RecordTests.fs | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/FSharpCoreReflectionProxy.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/FSharpCoreReflectionProxy.cs index e0bd83a0c1c9bf..835da6e002f905 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/FSharpCoreReflectionProxy.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/FSharpCoreReflectionProxy.cs @@ -204,7 +204,10 @@ public Func>, TFSharpMap> CreateFSharpMapConstru } private Attribute? GetFSharpCompilationMappingAttribute(Type type) - => type.GetCustomAttribute(_compilationMappingAttributeType, inherit: true); + { + object[] attributes = type.GetCustomAttributes(_compilationMappingAttributeType, inherit: false); + return attributes.Length == 0 ? null : (Attribute)attributes[0]; + } private SourceConstructFlags GetSourceConstructFlags(Attribute compilationMappingAttribute) => _sourceConstructFlagsGetter is null ? SourceConstructFlags.None : (SourceConstructFlags)_sourceConstructFlagsGetter.Invoke(compilationMappingAttribute, null)!; @@ -212,7 +215,7 @@ private SourceConstructFlags GetSourceConstructFlags(Attribute compilationMappin // If the provided type is generated by the F# compiler, returns the runtime FSharp.Core assembly. private static Assembly? GetFSharpCoreAssembly(Type type) { - foreach (Attribute attr in type.GetCustomAttributes(inherit: true)) + foreach (Attribute attr in type.GetCustomAttributes(inherit: false)) { Type attributeType = attr.GetType(); if (attributeType.FullName == CompilationMappingAttributeTypeName) diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.FSharp.Tests/RecordTests.fs b/src/libraries/System.Text.Json/tests/System.Text.Json.FSharp.Tests/RecordTests.fs index d9ac41cbd2b41d..6044b692904ef4 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.FSharp.Tests/RecordTests.fs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.FSharp.Tests/RecordTests.fs @@ -76,3 +76,22 @@ let ``Recursive struct records are supported``() = Assert.Equal("""{"Next":[{"Next":[null]}]}""", json) let deserializedValue = JsonSerializer.Deserialize(json) Assert.Equal(value, deserializedValue) + + +[, "derived")>] +type BaseClass(x : int) = + member _.X = x + +and DerivedClass(x : int, y : bool) = + inherit BaseClass(x) + member _.Y = y + +[] +let ``Support F# class hierarchies`` () = + let value = DerivedClass(42, true) :> BaseClass + let json = JsonSerializer.Serialize(value) + Assert.Equal("""{"$type":"derived","Y":true,"X":42}""", json) + let deserializedValue = JsonSerializer.Deserialize(json) + let derived = Assert.IsType(deserializedValue) + Assert.Equal(42, deserializedValue.X) + Assert.Equal(true, derived.Y)