Skip to content

Extra encoder doesn't get called for type with generic params #169

@Arrow7000

Description

@Arrow7000

I have the following type that I want to encode:

type CstNode<'a> =
    { node : 'a
      source : TokenWithSource list }

but I only want to encode the node field's value directly, because the source is not necessary for serialisation, and it would just add clutter to the generated JSON.

I then try to encode a sample record using the following code

let cstNodeEncoder : Encoder<CstNode<'a>> =
    fun (cstNode : CstNode<'a>) ->
        printfn "Calling CstNode encoder" // Log this encoder
        // Encode only the .node field using an auto encoder
        Encode.Auto.generateEncoder () cstNode.node

// We don't care about the decoder because we are only ever going to encode the type
let cstNodeDecoder : Decoder<CstNode<'a>> = fun _ -> failwithf "Not implemented"

let cstCoder =
    Extra.empty
    |> Extra.withCustom cstNodeEncoder cstNodeDecoder

let toJson result =
    Encode.Auto.toString (4, value = result, extra = cstCoder)

[<EntryPoint>]
let main argv =
    { node = 1234; source = List.empty }
    |> List.singleton
    |> toJson
    |> printfn "%A"

    0

Yet I still consistently get this in my console

"[
    {
        "node": 1234,
        "source": []
    }
]"

So it looks like either Encode.Auto.generateEncoder () cstNode.node isn't actually doing anything, or that my extra encoder is never even being called. I'm leaning towards the latter because the printfn statement in the body of the encoder is never appearing in my console, so it looks like it's never being called.

Is it possible that this is because my type includes a generic type parameter which doesn't play nicely with the logic for checking whether a custom encoder needs to be invoked?

UPDATE: it looks like my suspicion was correct, because as soon as I make my encoder accept only a concrete type the encoder does get called

let cstNodeEncoder : Encoder<CstNode<int>> = // note the 'a has been replaced with an int

The console now says

Calling CstNode encoder
"[
    1234
]"

However my CstNode contains a wide variety of types across my codebase, so having to specify explicit encoders for each one would defeat the whole point of using an auto encoder; plus there'd be no way to verify that I've accounted for all the types of generic that CstNode contains across my codebase.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions