【问题标题】:Serializing F# Discriminated union as strings with Json.NET使用 Json.NET 将 F# 可区分联合序列化为字符串
【发布时间】:2018-04-25 03:04:40
【问题描述】:

我正在尝试在序列化时从 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

【问题讨论】:

    标签: json serialization f# json.net


    【解决方案1】:

    创建一个自定义的 Json.NET JsonConverter 并使用它来装饰有区别的联合(“枚举样式”)就足以让它按照我想要的方式工作。其中很大一部分是从@Brian Rogers 用 C# 回答 https://stackoverflow.com/a/22355712/1924257

    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
    

    【讨论】:

      【解决方案2】:

      如果您愿意将 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"}"
      

      【讨论】:

      猜你喜欢
      • 2014-09-13
      • 1970-01-01
      • 2014-09-15
      • 1970-01-01
      • 2013-09-09
      • 1970-01-01
      • 2017-01-24
      • 1970-01-01
      相关资源
      最近更新 更多