Callum Linington
Callum Linington

Reputation: 14417

F# Custom JsonConverter for Option

I'm trying to create an option type customer serialiser here is the JsonConverter

I've got:

type OptionConverter<'T> =
    inherit JsonConverter<'T>
    override __.WriteJson (writer: Utf8JsonWriter, value: 'T option, serializer: JsonSerializerOptions) : unit =
        match value with
        | Some optionValue -> 
            JsonSerializer.Serialize(writer, optionValue, serializer)
        | None -> 
            writer.WriteNullValue()

    override __.ReadJson (reader: byref<Utf8JsonWriter>, typeToConvert: Type, serializer: JsonSerializerOptions): 'T =
        failwith "Not implemented"

type OptionConverterFactory =
    inherit JsonConverterFactory
    override __.CanConvert(typeToConvert: Type) = 
        let isOption = if typeToConvert.GetGenericTypeDefinition() = typeof<option<_>> then true else false
        isOption
    override __.CreateConverter(typeToConvert: Type, options: JsonSerializerOptions) : JsonConverter =
        let optionType = typeToConvert.GetGenericArguments().[0]
        let converter = Activator.CreateInstance(typeof<OptionConverter<_>>.MakeGenericType([| optionType |])) :?> JsonConverter
        converter

I get red line underneath WriteJson saying no abstract or interface member found that corresponds with this override...

Also, if I change WriteJson and ReadJson to member then OptionConvert<'T> gets red underline saying that WriteJson and ReadJson have not been implemented...

How do I fix this?

Upvotes: 1

Views: 869

Answers (1)

Phillip Carter
Phillip Carter

Reputation: 5005

I think there are two problems here:

  1. The wrong methods are being overloaded
  2. You need to constrain your 'T to be an option.

This compiled:

open System
open System.Text.Json
open System.Text.Json.Serialization

type OptionConverter<'T> =
    inherit JsonConverter<option<'T>>

    override _.Write(writer, value, opts) =
        match value with
        | Some optionValue -> 
            JsonSerializer.Serialize(writer, optionValue, opts)
        | None -> 
            writer.WriteNullValue()

    override _.Read(_reader, _typeToConvert, _options) =
        failwith "Not implemented"

Upvotes: 3

Related Questions