EDIT: Neither of the answers below really meet your criteria, but I'm posting in case others looking for union-serialization find them useful. I don't know offhand of any library way to re-parse the output of sprintf "%A"
on a union - keep in mind that the compiler and FSI have a much different task, knowing scopes and dealing with namespaces and qualified names and shadowing and whatnot, and even ignoring that, parsing the data carried by the unions (ints, strings, arbitrary objects, etc.) is potentially a whole task in itself.
Here is one strategy for union serialization, as part of a small sample program. (KnownTypeAttribute
can take a method name, and you can use some reflection to get the types.) This is a very easy way to add a tiny bit of code to a union to get serialization.
open Microsoft.FSharp.Reflection
open System.Reflection
open System.Runtime.Serialization
open System.Xml
[<KnownType("KnownTypes")>]
type Union21WithKnownTypes =
| Case1 of int * int
| Case2 of string
static member KnownTypes() =
typeof<Union21WithKnownTypes>.GetNestedTypes(
BindingFlags.Public
||| BindingFlags.NonPublic) |> Array.filter FSharpType.IsUnion
let dcs = new DataContractSerializer(typeof<Union21WithKnownTypes[]>)
let arr = [| Case1(1,1); Case2("2") |]
printfn "orig data: %A" arr
let sb = new System.Text.StringBuilder()
let xw = XmlWriter.Create(sb)
dcs.WriteObject(xw, arr)
xw.Close()
let s = sb.ToString()
printfn ""
printfn "encoded as: %s" s
printfn ""
let xr = XmlReader.Create(new System.IO.StringReader(s))
let o = dcs.ReadObject(xr)
printfn "final data: %A" o
Here's the JSON version:
open Microsoft.FSharp.Reflection
open System.Reflection
open System.Runtime.Serialization
open System.Runtime.Serialization.Json
open System.Xml
[<KnownType("KnownTypes")>]
type Union21WithKnownTypes =
| Case1 of int * int
| Case2 of string
static member KnownTypes() =
typeof<Union21WithKnownTypes>.GetNestedTypes(
BindingFlags.Public
||| BindingFlags.NonPublic) |> Array.filter FSharpType.IsUnion
let dcs = new DataContractJsonSerializer(typeof<Union21WithKnownTypes[]>)
let arr = [| Case1(1,1); Case2("2") |]
printfn "orig data: %A" arr
let stream = new System.IO.MemoryStream()
dcs.WriteObject(stream, arr)
stream.Seek(0L, System.IO.SeekOrigin.Begin) |> ignore
let bytes = Array.create (int stream.Length) 0uy
stream.Read(bytes, 0, int stream.Length) |> ignore
let s = System.Text.Encoding.ASCII.GetString(bytes)
printfn ""
printfn "encoded as: %s" s
printfn ""
stream.Seek(0L, System.IO.SeekOrigin.Begin) |> ignore
let o = dcs.ReadObject(stream)
printfn "final data: %A" o