2014-03-13 20 views
7

我想这是太多我从框架要求。但只是想知道是否有可能。或者什么会解决这个问题。如何使用F#Union类型与Servicestack JSON序列化?

带有新版本的JSON.Net开始支持F#联合类型。这是什么工作,意味着如果我使用servicestack.text,那么我如何平坦化union类型来支持序列化。

这里是两者的代码示例。

type Shape = 
    | Rectangle of width : float * length : float 
    | Circle of radius : float 
    | Empty 


[<EntryPoint>] 
let main argv = 
// printfn "%A" argv 
    let shape1 = Rectangle(1.3, 10.0) 

    let json = JsonConvert.SerializeObject(shape1) //JSON.net 
    printfn "%A" json 
    // { 
    // "Case": "Rectangle", 
    // "Fields": [ 
    //  1.3, 
    //  10.0 
    // ] 
    // } 

    let shape2 = JsonConvert.DeserializeObject<Shape>(json) //JSON.Net 
    printfn "%A" (shape2 = shape1) //true 

    let sJson = JsonSerializer.SerializeToString shape1 //SS.Text 
    printfn "%A" sJson 

    let sShape2 = JsonSerializer.DeserializeFromString sJson //SS.Text 
    printfn "%A" (sShape2 = shape1) //false 

    Console.Read() |> ignore 
    0 // return an integer exit code 

使用servicestack反序列化返回false。与JSON.net相比,生成的json字符串也相当复杂。

如何实现Union类型的正确序列化?

回答

2

您必须给ServiceStack一个自定义序列化程序。它会像现在这样,使用简洁形状小类型:

open ServiceStack.Text 

type Shape = 
    | Circle of float 
    | Empty 

JsConfig<Shape>.SerializeFn 
    <- Func<_,_> (function 
        | Circle r -> sprintf "C %f" r 
        | Empty -> sprintf "E") 

JsConfig<Shape>.DeSerializeFn 
    <- Func<_,_> (fun s ->  
        match s.Split [| |] with 
        | [| "C"; r |] -> Circle (float r) 
        | [| "E" |] -> Empty) 

let shapes = [| Circle 8.0 |] 
let json = JsonSerializer.SerializeToString(shapes) 
let shapes1 = JsonSerializer.DeserializeFromString<Shape[]>(json) 
let is_ok = shapes = shapes1 

此代码不能在解串器适当的异常传播:你要处理的match不匹配,并可能floatSystem.FormatException

+0

它的工作原理。我已经在小组讨论过这个话题。我开始了解羊毛。如果你也可以用它的一个样本更新答案,那将是非常好的。我想这将解决有关将联合类型序列化为JSON的问题。 – kunjee

相关问题