简体   繁体   English

如何使用Servicestack JSON序列化的F#Union类型?

[英]How to use F# Union types with Servicestack JSON serialization?

I guess it is too much I am asking from a framework. 我想从框架中提出的问题太多了。 But just wondering if it is possible at all. 但只是想知道它是否有可能。 Or what will be work around for this. 或者将会解决这个问题。

JSON.Net with new release started supporting F# union types. 新版本的JSON.Net开始支持F#union类型。 What is the work around for that, means if I am using servicestack.text, then how can I flatten union types to support serialization. 解决这个问题的方法是什么,这意味着如果我使用servicestack.text,那么我如何展平联合类型以支持序列化。

Here is code sample for both. 这是两者的代码示例。

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

Deserialization using servicestack is returning false. 使用servicestack进行反序列化返回false。 And also generated json string is quite complicated in compare to JSON.net. 与JSON.net相比,生成的json字符串相当复杂。

How to achieve proper serialization for Union types? 如何为Union类型实现正确的序列化?

You'll have to give ServiceStack a custom serializer. 您必须为ServiceStack提供自定义序列化程序。 It would like this, using a smaller Shape type for brevity: 它想要这样,使用较小的Shape类型以简化:

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

This code does not have proper exception-propagation in the deserializer: you'd want to handle the match not matching, and float might raise a System.FormatException . 此代码在反序列化器中没有正确的异常传播:您希望处理match不匹配,并且float可能引发System.FormatException

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM