Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/FSharp.SystemTextJson/All.fs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ type JsonFSharpConverter(fsOptions: JsonFSharpOptions, [<Optional>] 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
Expand Down
12 changes: 12 additions & 0 deletions src/FSharp.SystemTextJson/TypeCache.fs
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -38,6 +40,16 @@ module TypeCache =
elif FSharpType.IsRecord(ty, true) then TypeKind.Record
else TypeKind.Other
)

let hasCustomJsonConverter =
let cache = Dict<System.Type, bool>()
fun (ty: System.Type) ->
cache.GetOrAdd(
ty,
fun ty ->
CustomAttributeData.GetCustomAttributes(ty)
|> Seq.exists (fun cad -> cad.AttributeType = typeof<JsonConverterAttribute>)
)

let isUnion ty =
getKind ty = TypeKind.Union
Expand Down
39 changes: 39 additions & 0 deletions tests/FSharp.SystemTextJson.Tests/Test.Union.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2482,6 +2482,45 @@ module Struct =
"""{"Case":"Unwrapped","Fields":["foo"]}""",
JsonSerializer.Serialize(Unwrapped "foo", noNewtypeOptions)
)




[<JsonConverter(typeof<TruthConverter>)>]
type Truth =
| True
| False
| FileNotFound
and TruthConverter() =
inherit JsonConverter<Truth>()

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

[<Fact>]
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<Truth>("\"lost\"",options))
Assert.Equal(True, JsonSerializer.Deserialize<Truth>("\"true\"",options))
Assert.Equal(False, JsonSerializer.Deserialize<Truth>("\"false\"",options))

module UnwrapRecord =

Expand Down