serialization - 无法在 F# Chiron 中序列化受歧视的联盟

标签 serialization f# discriminated-union

如果我有:

type a = B | C

如何编写静态成员 ToJson 和 FromJson?

我知道如何为记录类型编写它(在 Chiron: JSON + Ducks + Monads 的示例中显示)但我找不到 DU 的任何示例。


编辑

在 s952163 有用的答案(和后续评论)之后,我调整了代码以尝试使用选择 A | 的“简单”DU B(而不是字符串 A | B of ...)。我的代码现在是:

type SimpleDU =
    | A
    | B
    static member ToJson (t : SimpleDU) =
        match t with
        | A -> Json.writeNone "a"
        | B -> Json.writeNone "b"
    static member FromJson (_ : SimpleDU) =    
        json {
            let! duA = Json.tryRead "a"
            match duA with
            | Some s -> return s
            | None ->   return SimpleDU.B
        }

这会编译,但是当我用示例操作代码尝试它时:

let a = A
let b = B
let a2json = a |> Json.serialize
let (json2a:SimpleDU) =  a2json |> Json.deserialize
let b2json = b |> Json.serialize 
let (json2b:SimpleDU) = b2json |> Json.deserialize 

json2a 错误地返回了 SimpleDU.B

最佳答案

A 序列化为 Object (map [("SimpleDU", String "a")]) 而不是 Object (map [("a", Null null)]) 是:

#I @"..\packages\Chiron.6.1.0\lib\net40"
#I @"..\packages\Aether.8.1.2\lib\net35"
#r "Chiron.dll"
#r "Aether.dll"

open Chiron

type SimpleDU = 
    | A
    | B

    static member ToJson x =
        Json.write "SimpleDU" <|
            match x with
            | A -> "a"
            | B -> "b"

    static member FromJson(_ : SimpleDU) = 
        json { 
            let! du = Json.tryRead "SimpleDU"
            match du with
            | Some "a" -> return A
            | Some "b" -> return B
            | Some x -> return! Json.error <| sprintf "%s is not a SimpleDU case" x
            | _ -> return! Json.error "Not a SimpleDU JSON"
        }

// val serializedA : Json = Object (map [("SimpleDU", String "a")])
let serializedA = A |> Json.serialize
let serializedB = B |> Json.serialize
let (a : SimpleDU) = serializedA |> Json.deserialize
let (b : SimpleDU) = serializedB |> Json.deserialize
let aMatches = a = A
let bMatches = b = B
let serializedABBAA = [ A; B; B; A; A ] |> Json.serialize
let (abbaa : SimpleDU list) = serializedABBAA |> Json.deserialize
let abbaaMatches = abbaa = [ A; B; B; A; A ]
// allFine = true
let allFine = aMatches && bMatches && abbaaMatches

let defects = 
    Array [ Object <| Map.ofList [ ("SimpleDU", String "c") ]
            Object <| Map.ofList [ ("Foo", String "bar") ] ]

// attempt = Choice2Of2 "Not a SimpleDU JSON"
let (attempt : Choice<SimpleDU list, string>) = defects |> Json.tryDeserialize

您可以使用 truefalse 而不是 "a""b" Some x 案例,但我宁愿在 JSON 中有可读的案例。

关于serialization - 无法在 F# Chiron 中序列化受歧视的联盟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37303265/

相关文章:

Java 未经检查或不安全操作消息

.net - 搜索中的重要数据结构

build - 如何禁用 FSharpLint 中的特定规则?

javascript - 期待并集和交集的类型错误

inheritance - 受歧视的工会和继承

java - 特定字段上的自定义 Jackson 序列化程序

android - Gson在条件下忽略序列化字段

c++ - 读写类对象到二进制文件

recursion - 为什么 F# 对堆栈大小施加下限?

f# - 枚举与非成员歧视工会