Skip to content

Serialize F# struct unions as a normal struct (flatten the case fields) #1547

@cmeeren

Description

@cmeeren

F# 4.1 allows discriminated unions to be represented as structs. In such unions, all case fields must have names that are unique across all cases.

I suggest that such unions should by default (or at least optionally) be serialized as a normal struct/class instead of using the special union serialization. This would make it much easier to make the serialized result of unions more compatible with other languages that don't have any concept of unions.

For example, given the following type and values:

[<Struct>]
type Foo = 
  | Case1 of foo: int
  | Case2 of bar: float * baz: string

let foo1 = Case1 2
let foo2 = Case2 (3.0, "qwerty")

Values should be serialized like this:

{
  Case: "Case1",
  foo: 2
}
{
  Case: "Case2",
  bar: 3.0,
  baz: "qwerty"
}

These serializations are much easier to deserialize in other typed languages that don't have any concept of unions; for example, this C# class:

class Foo {

  enum Case { Case1, Case2 }

  public Case Case { get; set; }
  public int Foo { get; set; }
  public double Bar { get; set; }
  public string Baz { get; set; }
}

Note that the C# example above could cause problems when going the other way, since by default (AFAIK) Case would be serialized as an int. I therefore suggest that when deserializing to the F# Foo type, both case names (string) and tags (ints) are handled.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions