From f3ceac57f983aa822dac1467e92f4adb8ef26857 Mon Sep 17 00:00:00 2001 From: Michel Bieleveld Date: Tue, 10 Mar 2026 22:36:47 -0300 Subject: [PATCH 1/3] Added check for existing JsonConverter --- src/FSharp.SystemTextJson/All.fs | 3 ++ src/FSharp.SystemTextJson/TypeCache.fs | 12 ++++++ .../FSharp.SystemTextJson.Tests/Test.Union.fs | 39 +++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/src/FSharp.SystemTextJson/All.fs b/src/FSharp.SystemTextJson/All.fs index dda4656..2394d9d 100644 --- a/src/FSharp.SystemTextJson/All.fs +++ b/src/FSharp.SystemTextJson/All.fs @@ -2,6 +2,7 @@ namespace System.Text.Json.Serialization open System open System.Collections.Generic +open System.Reflection open System.Runtime.CompilerServices open System.Runtime.InteropServices open System.Text.Json @@ -20,6 +21,8 @@ type JsonFSharpConverter(fsOptions: JsonFSharpOptions, [] overrides: I member _.Overrides = fsOptions.Overrides override _.CanConvert(typeToConvert) = + not (TypeCache.hasCustomJsonConverter typeToConvert) + && match TypeCache.getKind typeToConvert with | TypeCache.TypeKind.List -> fsOptions.Types.HasFlag JsonFSharpTypes.Lists | TypeCache.TypeKind.Set -> fsOptions.Types.HasFlag JsonFSharpTypes.Sets diff --git a/src/FSharp.SystemTextJson/TypeCache.fs b/src/FSharp.SystemTextJson/TypeCache.fs index cd904e6..bd8f8d9 100644 --- a/src/FSharp.SystemTextJson/TypeCache.fs +++ b/src/FSharp.SystemTextJson/TypeCache.fs @@ -1,5 +1,7 @@ namespace System.Text.Json.Serialization +open System.Reflection + module TypeCache = open FSharp.Reflection @@ -38,6 +40,16 @@ module TypeCache = elif FSharpType.IsRecord(ty, true) then TypeKind.Record else TypeKind.Other ) + + let hasCustomJsonConverter = + let cache = Dict() + fun (ty: System.Type) -> + cache.GetOrAdd( + ty, + fun ty -> + CustomAttributeData.GetCustomAttributes(ty) + |> Seq.exists (fun cad -> cad.AttributeType = typeof) + ) let isUnion ty = getKind ty = TypeKind.Union diff --git a/tests/FSharp.SystemTextJson.Tests/Test.Union.fs b/tests/FSharp.SystemTextJson.Tests/Test.Union.fs index aacd204..71242ad 100644 --- a/tests/FSharp.SystemTextJson.Tests/Test.Union.fs +++ b/tests/FSharp.SystemTextJson.Tests/Test.Union.fs @@ -2482,6 +2482,45 @@ module Struct = """{"Case":"Unwrapped","Fields":["foo"]}""", JsonSerializer.Serialize(Unwrapped "foo", noNewtypeOptions) ) + + + + + [)>] + type Truth = + | True + | False + | FileNotFound + and TruthConverter() = + inherit JsonConverter() + + override _.Write(writer, value, _options) = + writer.WriteStringValue( + match value with + | FileNotFound -> "lost" + | True -> "true" + | False -> "false" + ) + + override _.Read(reader, _typeToConvert, _options) = + match reader.GetString() with + | "lost" -> FileNotFound + | "true" -> True + | "false" -> False + | other -> failwithf "Unknown Truth value: %s" other + + [] + let ``custom converter wins over FSharp.SystemTextJson`` () = + let options = + JsonFSharpOptions.Default().ToJsonSerializerOptions() + + Assert.Equal("\"lost\"", JsonSerializer.Serialize( FileNotFound, options)) + Assert.Equal("\"true\"", JsonSerializer.Serialize( True, options)) + Assert.Equal("\"false\"", JsonSerializer.Serialize( False, options)) + + Assert.Equal(FileNotFound, JsonSerializer.Deserialize("\"lost\"",options)) + Assert.Equal(True, JsonSerializer.Deserialize("\"true\"",options)) + Assert.Equal(False, JsonSerializer.Deserialize("\"false\"",options)) module UnwrapRecord = From 362c23efa505bcaf20544646368bde56ca0f65bc Mon Sep 17 00:00:00 2001 From: Michel Bieleveld Date: Tue, 10 Mar 2026 22:41:51 -0300 Subject: [PATCH 2/3] Added check for existing JsonConverter, cleaned up open --- src/FSharp.SystemTextJson/All.fs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/FSharp.SystemTextJson/All.fs b/src/FSharp.SystemTextJson/All.fs index 2394d9d..357d5bb 100644 --- a/src/FSharp.SystemTextJson/All.fs +++ b/src/FSharp.SystemTextJson/All.fs @@ -2,7 +2,6 @@ namespace System.Text.Json.Serialization open System open System.Collections.Generic -open System.Reflection open System.Runtime.CompilerServices open System.Runtime.InteropServices open System.Text.Json From 35fe7147179202ebe13cae7e32e0b31f98feb2f1 Mon Sep 17 00:00:00 2001 From: Michel Bieleveld Date: Tue, 10 Mar 2026 22:43:21 -0300 Subject: [PATCH 3/3] Added check for existing JsonConverter, cleaned up open --- src/FSharp.SystemTextJson/TypeCache.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FSharp.SystemTextJson/TypeCache.fs b/src/FSharp.SystemTextJson/TypeCache.fs index bd8f8d9..97de001 100644 --- a/src/FSharp.SystemTextJson/TypeCache.fs +++ b/src/FSharp.SystemTextJson/TypeCache.fs @@ -1,9 +1,9 @@ namespace System.Text.Json.Serialization -open System.Reflection module TypeCache = open FSharp.Reflection + open System.Reflection // Have to use concurrentdictionary here because dictionaries thrown on non-locked access: (* Error Message: