Skip to content

Documenting different ways to encode DUs #103

@Choc13

Description

@Choc13

It seems there are (at least) a couple of ways that people encode DUs in JSON.

The first way, which is currently documented, uses the case name as the property name which then encloses that case's data. For example the following F# type

type Foo = { X: int }
type Bar = { Y: string }

type Baz =
    | Foo of Foo
    | Bar of Bar

The Foo case would be encoded as

{
    "foo": {
        "x": 1
    }
}

And the Bar case would be encoded as:

{
    "bar": {
        "y": "string"
    }
}

I think this way makes a lot of sense when you want to round trip to a DU on both sides.

A second way, which isn't documented, that is common if you're using TypeScript on the client is to enclose the case label under some "tag" prop. This is even more relevant I think if you have some DU cases that don't have any data. For example:

type Foo = { X: int }

type Baz =
    | Foo of Foo
    | Bar 

Then the Foo case would be encoded as:

{
    "type": "foo",
    "x": 1
}

And the Bar case would be:

{
    "type": "bar"
}

Where obviously the "type" field could be named anything.

I think this second case needs documenting, along with any other ways of commonly encoding DUs, as it's not immediately obvious how to build a codec for this second type.

I think the way you want to go about writing the codec for this second way is to start with codecs for the data in each of the case labels and then apply a combinator that adds a tag prop for the relevant case and (maybe a second combinator) that lifts the codec into the DU type by applying the case constructor when decoding and unwrapping the value when encoding. You then want to use an alternative to bring all of those codecs together.

I'm happy to open a PR to improve the docs to add an example for the second case.

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