使用Json.NET将F#鉴别联合序列化为字符串

9
我正在尝试对F#的判别式联合进行单向转换,以字符串方式进行序列化,而不是使用默认的`"Case": [value]`。重新反序列化该值并不是问题。也许可以用Json.NET实现?
// Fsharp 4.1.0
open Newtonsoft.Json // 10.0.3

type HowLame =
| PrettyLame
| SuperLame

type Lame = {
    howLame: HowLame;
}

[<EntryPoint>]
let main argv =
    let lame = { howLame = PrettyLame }
    let ser = JsonConvert.SerializeObject(lame)

    // {"soLame":{"Case":"PrettyLame"}} by default
    printfn "%s" ser

    // Desired
    assert (ser = """{"soLame":"PrettyLame"}""")
    0 // return an integer exit code
2个回答

9

创建一个自定义的Json.NET JsonConverter并将其用于装饰区分联合(“枚举样式”)就足以使此功能按照我想要的方式工作。其中很大一部分是从@Brian Rogers在C#中的答案中转录的https://dev59.com/JmEh5IYBdhLWcg3wfjiq#22355712

open System
open Newtonsoft.Json // 10.0.3
open Newtonsoft.Json.Converters

type ToStringJsonConverter () =
    inherit JsonConverter()
    override this.CanConvert objectType = true;

    override this.WriteJson (writer: JsonWriter, value: obj, serializer: JsonSerializer): unit = 
        writer.WriteValue(value.ToString())

    override this.CanRead = false

    override this.ReadJson (reader: JsonReader, objectType: Type, existingValue: obj, serializer: JsonSerializer) : obj =
        raise (new NotImplementedException());

[<JsonConverter(typeof<ToStringJsonConverter>)>]
type HowLame =
| PrettyLame
| SuperLame

type Lame = {
    howLame: HowLame
}

[<EntryPoint>]
let main argv =
    let lame = { howLame = PrettyLame }
    let ser = JsonConvert.SerializeObject(lame)

    // {"howLame":"PrettyLame"}
    printfn "%s" ser

    0 // return an integer exit code

7
如果你愿意把本文中的 DU 定义为枚举类型(通过指定值,因为它没有“有效载荷”,这很可能是可行的),那么你可以使用标准的StringEnumConverter
#r "../packages/Newtonsoft.Json/lib/net45/Newtonsoft.Json.dll"
open Newtonsoft.Json

type HowLame = PrettyLame=0 | SuperLame=1
type Lame = { howLame: HowLame; }

// in contrast to DUs, enums must be qualified, i.e. Enum.Value
let lame = { howLame = HowLame.PrettyLame }

let settings = JsonSerializerSettings()
settings.Converters.Add(Converters.StringEnumConverter())

let ser = JsonConvert.SerializeObject(lame, settings)
// val ser : string = "{"howLame":"PrettyLame"}"

1
此外,请查看Json.FSharp,特别是UnionConverter,也许还有Chiron - CaringDev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接