Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Serialization 无法序列化F#Chiron中的歧视联合_Serialization_F#_Discriminated Union - Fatal编程技术网

Serialization 无法序列化F#Chiron中的歧视联合

Serialization 无法序列化F#Chiron中的歧视联合,serialization,f#,discriminated-union,Serialization,F#,Discriminated Union,如果我有: type a = B | C 如何将静态成员写入JSON和FromJson 我知道如何为记录类型编写它(如中的示例所示),但我找不到DU的任何示例 编辑 在s952163给出了有用的答案(以及后续的评论)之后,我对代码进行了调整,以尝试使用选择a | B的“简单”DU(而不是字符串B的…)。我的代码是: type SimpleDU = | A | B static member ToJson (t : SimpleDU) = match t

如果我有:

type a = B | C
如何将静态成员写入JSON和FromJson

我知道如何为记录类型编写它(如中的示例所示),但我找不到DU的任何示例


编辑

在s952163给出了有用的答案(以及后续的评论)之后,我对代码进行了调整,以尝试使用选择a | B的“简单”DU(而不是字符串B的…)。我的代码是:

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

您也可以向DU添加静态成员。在最后一段中,有一个链接提到一些DU的例子应该很快就会出现。但是,假设您不能等待,并且您更喜欢Chiron而不是Json.NET,或者这里是一个示例。可能还有其他方法,但我不熟悉Chiron的运算符,所以我决定使用一个计算表达式(从中窃取)。这样做的目的是,您可以进行模式匹配。因此,您也可以在更复杂的DU上进行模式匹配。如果你熟悉凯龙,我相信它会更地道。您可以看到Chiron本身正在使用DU,例如Json对象是map

#I @"..\packages\Chiron.6.1.0\lib\net40"
#I @"..\packages\Aether.8.0.2\lib\net35"
#I @"..\packages\FParsec.1.0.1\lib\net40-client"
#r "Chiron.dll"
#r "Aether.dll"
#r "Fparsec.dll"

open Aether
open Chiron
open Chiron.Operators
open FParsec

type SimpleDU =
    |A of string
    |B of int * bool
    static member ToJson (x: SimpleDU) =
        match x with
        | A s -> Json.write "A" s
        | B (i, b) -> Json.write "B" (i, b)
    static member FromJson (_ : SimpleDU) =    
      json {
        let! duA = Json.tryRead "A"
        match duA with
        | Some s -> return A s
        | None ->
          let! x = Json.read "B"
          return B x
      }
下面是它的工作原理:

let a = A "Jason"
let b = B (13,true)
let a2json = a |> Json.serialize //val Json = Object (map [("A", String "Jason")])
let (json2a:SimpleDU) =  a2json |> Json.deserialize //val json2a : SimpleDU = A "Jason"
let b2json = b |> Json.serialize 
let (json2b:SimpleDU) = b2json |> Json.deserialize 
源代码中也有一些可能对您有用的示例:

在我看来可能对您有所帮助。这个答案指向为有区别的联合定义
ToString
FromString
函数:

open Microsoft.FSharp.Reflection

let toString (x:'a) = 
    match FSharpValue.GetUnionFields(x, typeof<'a>) with
    | case, _ -> case.Name

let fromString<'a> (s:string) =
    match FSharpType.GetUnionCases typeof<'a> |> Array.filter (fun case -> case.Name = s) with
    |[|case|] -> Some(FSharpValue.MakeUnion(case,[||]) :?> 'a)
    |_ -> None
打开Microsoft.FSharp.Reflection
让toString(x:'a)=
匹配FSharpValue.GetUnionFields(x,typeof(s:string)=
匹配FSharpType.GetUnionCases类型无

您仍然需要从字符串(仅“A”或“B”)到完整的DU对象(例如,在s952163的
SimpleDU
示例中读取DU的其余数据),并且由于我还没有使用Chiron,在这方面我帮不了您多少忙。但这可能会给您一个起点。

一个将
A
序列化到
对象的实现(映射[(“SimpleDU”,字符串“a”)])
而不是
对象(映射[(“a”,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
#I@.\packages\Chiron.6.1.0\lib\net40
#I@“.\packages\ether.8.1.2\lib\net35”
#r“Chiron.dll”
#r“ether.dll”
开凯龙
类型SimpleDU=
|A
|B
静态成员tox=
Json.write“SimpleDU”“a”
|B->“B”
来自JSON的静态成员(uz:SimpleDU)=
json{
让!du=Json.tryRead“SimpleDU”
配
|有些“a”->返回a
|一些“b”->返回b
|Some x->return!Json.error return!Json.error“不是SimpleDU Json”
}
//val serializedA:Json=Object(映射[(“SimpleDU”,字符串“a”))
让serializedA=A |>Json.serialize
让serializedB=B |>Json.serialize
让(a:SimpleDU)=serializedA |>Json.deserialize
let(b:SimpleDU)=serializedB |>Json.deserialize
设aMatches=a=a
设b匹配=b=b
让serializedABBAA=[A;B;B;A;A]|>Json.serialize
let(abbaa:SimpleDU list)=序列化dabbaa |>Json.deserialize
让abbamatches=abbaa=[A;B;B;A;A]
//一切正常
让allFine=aMatches&&b匹配&&abbamatches
让缺陷=

Array[Object说到general f#Yan Cui发表了一篇关于它的文章。看看:你的意思是想使用一个选择(比如Choice1of2)类型还是只使用这个简单的DU?我现在无法测试它,但你可能可以在
Json之后输入一些伪值。写“a”
“a”
bu您可能也想
返回s
。但感觉有点笨拙……您能看一下,看看这是否解决了您的问题吗。@s952163这越来越近了,非常感谢您的帮助,但它仍然不太有效。我再次编辑了问题,以显示我现在的状态。这意味着n match未能匹配“a”并返回无。尝试在没有B的情况下进行匹配,可能会出现错误。这可能与Chiron有关,也可能是let!语法。检查let!=duAI中的内容。假设有一种方法可以使用不同的语法进行模式匹配。顺便问一句,您是否锁定Chiron?