diff --git a/src/FSharp.SystemTextJson/All.fs b/src/FSharp.SystemTextJson/All.fs index dda4656..357d5bb 100644 --- a/src/FSharp.SystemTextJson/All.fs +++ b/src/FSharp.SystemTextJson/All.fs @@ -20,6 +20,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..97de001 100644 --- a/src/FSharp.SystemTextJson/TypeCache.fs +++ b/src/FSharp.SystemTextJson/TypeCache.fs @@ -1,7 +1,9 @@ namespace System.Text.Json.Serialization + module TypeCache = open FSharp.Reflection + open System.Reflection // Have to use concurrentdictionary here because dictionaries thrown on non-locked access: (* Error Message: @@ -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 =