Search code examples
f#elmishsafe-stack

How do I write encoders/decoders for Thoth.Json in the SAFE Stack?


I'm building an application using the SAFE Stack and I have a System.Uri in my model. When I run my code I get an error in the console "Cannot generate autoencoder for System.Uri..."
My googling has got me to here so far

module CustomEncoders

open Thoth.Json
let uriEncoder (uri:System.Uri) = Encode.string (uri.ToString())

let uriDecoder = ????

let myExtraCoders =
    Extra.empty
    |> Extra.withCustom uriEncoder uriDecoder 


let modelEncoder = Encode.Auto.generateEncoder(extra = myExtraCoders)
let modelDecoder = Decode.Auto.generateDecoder(extra = myExtraCoders)

Then in my App.fs I add

|> Program.withDebuggerCoders CustomEncoders.modelEncoder CustomEncoders.modelDecoder

I think I have understood how to create an encoder but I have no idea how to write the decoder part.
I could obviously replace my System.Uri fields with string but that doesn't feel like the right solution.


Solution

  • Looking at the Decoder Type, It has the following signature string -> JsonValue -> Result<'T, DecoderError>

    Where

    • string: json path to select from the json value
    • JsonValue: raw json to decode

    And it either returns an Ok<'T> or Error<DecoderError>

    So your uri Decoder will be as follows

    let uriDecoder path (token: JsonValue) =
        let value = token.Value<string>()
        match System.Uri.TryCreate(value, System.UriKind.Absolute) with
        | (true, uri) -> Ok uri
        | (false, _) -> Error (path, BadPrimitive("Uri", token))