문제

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. What is the work around for that, means if I am using servicestack.text, then how can I flatten union types to support serialization.

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. And also generated json string is quite complicated in compare to JSON.net.

How to achieve proper serialization for Union types?

도움이 되었습니까?

해결책

You'll have to give ServiceStack a custom serializer. It would like this, using a smaller Shape type for brevity:

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top