diff --git a/src/Decode.fs b/src/Decode.fs index dee40ee..3f3536f 100644 --- a/src/Decode.fs +++ b/src/Decode.fs @@ -1264,7 +1264,7 @@ module Decode = and private autoDecodeRecordsAndUnions extra (caseStrategy : CaseStrategy) (isOptional : bool) (t: System.Type): BoxedDecoder = // Add the decoder to extra in case one of the fields is recursive let decoderRef = ref Unchecked.defaultof<_> - let extra = extra |> Map.add t.FullName decoderRef + let extra = extra |> Map.add (getTypeName t) decoderRef let decoder = if FSharpType.IsRecord(t, allowAccessToPrivateRepresentation=true) then let decoders = @@ -1301,8 +1301,8 @@ Documentation available at: https://thoth-org.github.io/Thoth.Json/documentation decoder - and private autoDecoder (extra: Map>) caseStrategy (isOptional : bool) (t: System.Type) : BoxedDecoder = - let fullname = t.FullName + and private autoDecoder (extra: Map>) caseStrategy (isOptional : bool) (t: System.Type) : BoxedDecoder = + let fullname = getTypeName t match Map.tryFind fullname extra with | Some decoderRef -> boxDecoder(fun path value -> decoderRef.contents.BoxedDecoder path value) | None -> @@ -1380,29 +1380,29 @@ If you can't use one of these types, please pass an extra decoder. Documentation available at: https://thoth-org.github.io/Thoth.Json/documentation/auto/extra-coders.html#ready-to-use-extra-coders """ t.FullName else - if fullname = typeof.FullName then + if fullname = getTypeName typeof then boxDecoder bool - elif fullname = typedefof.FullName then + elif fullname = getTypeName typedefof then boxDecoder unit - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder string - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder char - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder sbyte - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder byte - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder int16 - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder uint16 - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder int - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder uint32 - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder float - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder float32 // These number types require extra libraries in Fable. To prevent penalizing // all users, extra decoders (withInt64, etc) must be passed when they're needed. @@ -1415,15 +1415,15 @@ Documentation available at: https://thoth-org.github.io/Thoth.Json/documentation // boxDecoder bigint // elif fullname = typeof.FullName then // boxDecoder decimal - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder datetimeUtc - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder datetimeOffset - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder timespan - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder guid - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxDecoder (fun _ v -> if Helpers.isNullValue v then Ok(null: obj) else v.Value() |> Ok) diff --git a/src/Encode.fs b/src/Encode.fs index 8161105..e322e73 100644 --- a/src/Encode.fs +++ b/src/Encode.fs @@ -369,17 +369,17 @@ module Encode = (d :?> EncoderCrate<'T>).UnboxedEncoder let private (|StringifiableType|_|) (t: System.Type): (obj->string) option = - let fullName = t.FullName - if fullName = typeof.FullName then + let fullName = getTypeName t + if fullName = getTypeName typeof then Some unbox - elif fullName = typeof.FullName then + elif fullName = getTypeName typeof then Some(fun (v: obj) -> (v :?> System.Guid).ToString()) else None let rec private autoEncodeRecordsAndUnions extra (caseStrategy : CaseStrategy) (skipNullField : bool) (t: System.Type) : BoxedEncoder = // Add the encoder to extra in case one of the fields is recursive let encoderRef = ref Unchecked.defaultof<_> - let extra = extra |> Map.add t.FullName encoderRef + let extra = extra |> Map.add (getTypeName t) encoderRef let encoder = if FSharpType.IsRecord(t, allowAccessToPrivateRepresentation=true) then let setters = @@ -439,8 +439,8 @@ Documentation available at: https://thoth-org.github.io/Thoth.Json/documentation ar.Add(encoder.Encode(x)) ar :> JsonValue) - and private autoEncoder (extra: Map>) caseStrategy (skipNullField : bool) (t: System.Type) : BoxedEncoder = - let fullname = t.FullName + and private autoEncoder (extra: Map>) caseStrategy (skipNullField : bool) (t: System.Type) : BoxedEncoder = + let fullname = getTypeName t match Map.tryFind fullname extra with | Some encoderRef -> boxEncoder(fun v -> encoderRef.contents.BoxedEncoder v) | None -> @@ -521,29 +521,29 @@ Thoth.Json.Net only support the folluwing enum types: If you can't use one of these types, please pass an extra encoder. """ t.FullName else - if fullname = typeof.FullName then + if fullname = getTypeName typeof then boxEncoder bool - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder unit - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder string - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder char - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder sbyte - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder byte - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder int16 - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder uint16 - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder int - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder uint32 - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder float - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder float32 // These number types require extra libraries in Fable. To prevent penalizing // all users, extra encoders (withInt64, etc) must be passed when they're needed. @@ -556,15 +556,15 @@ If you can't use one of these types, please pass an extra encoder. // boxEncoder bigint // elif fullname = typeof.FullName then // boxEncoder decimal - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder datetime - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder datetimeOffset - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder timespan - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder guid - elif fullname = typeof.FullName then + elif fullname = getTypeName typeof then boxEncoder(fun (v: obj) -> JValue(v) :> JsonValue) else autoEncodeRecordsAndUnions extra caseStrategy skipNullField t diff --git a/src/Extra.fs b/src/Extra.fs index 65b92b0..84aa75b 100644 --- a/src/Extra.fs +++ b/src/Extra.fs @@ -10,7 +10,7 @@ let inline internal withCustomAndKey (encoder: Encoder<'Value>) (decoder: Decode { extra with Hash = System.Guid.NewGuid().ToString() Coders = - extra.Coders |> Map.add typeof<'Value>.FullName (Encode.boxEncoder encoder, Decode.boxDecoder decoder) } + extra.Coders |> Map.add (getTypeName typeof<'Value>) (Encode.boxEncoder encoder, Decode.boxDecoder decoder) } let inline withCustom (encoder: Encoder<'Value>) (decoder: Decoder<'Value>) (extra: ExtraCoders): ExtraCoders = withCustomAndKey encoder decoder extra diff --git a/src/Helpers.fs b/src/Helpers.fs new file mode 100644 index 0000000..ae4919a --- /dev/null +++ b/src/Helpers.fs @@ -0,0 +1,6 @@ +namespace Thoth.Json.Net + +[] +module internal Helpers = + + let getTypeName (t : System.Type) : TypeName = (t.GetGenericTypeDefinition ()).FullName |> TypeName diff --git a/src/Thoth.Json.Net.fsproj b/src/Thoth.Json.Net.fsproj index 9d173a3..e14cf8d 100644 --- a/src/Thoth.Json.Net.fsproj +++ b/src/Thoth.Json.Net.fsproj @@ -28,6 +28,7 @@ + diff --git a/src/Types.fs b/src/Types.fs index c25ae12..945bc1e 100644 --- a/src/Types.fs +++ b/src/Types.fs @@ -36,9 +36,12 @@ type BoxedEncoder() = abstract Encode: value: obj -> JsonValue member this.BoxedEncoder: Encoder = this.Encode +/// Represents the `.GetGenericTypeDefinition().FullName` of a type +type TypeName = TypeName of string + type ExtraCoders = { Hash: string - Coders: Map } + Coders: Map } module internal Cache = open System