使用Newtonsoft.Json反序列化F#中的私有类型

时间:2019-12-13 13:19:06

标签: json f#

使用Newtonsoft.Json时,如何反序列化私有类型?例如:

[<CLIMuteable>]
type private Foo = {
  Bar:string
}

module Foo =
  let deserialize str=
      str |> Newtonsoft.Json.JsonCovert.DeserializeObject<Foo>

1 个答案:

答案 0 :(得分:2)

这听起来很不寻常,但是我认为您有充分的理由使用私有类型。

这里的问题是Json.NET无法看到该类型上的任何公共属性,您可以通过使用自定义合同解析器来解决此问题,并告诉它查找私有成员。

赞:

open System
open System.Reflection
open FSharp.Core
open Newtonsoft.Json
open Newtonsoft.Json.Serialization

[<CLIMutable>]
type private Foo = {
  Bar:string
}

type PrivateContractResolver() =
    inherit DefaultContractResolver()
    override this.GetSerializableMembers(objectType : Type) = 
        let flags = BindingFlags.Instance ||| BindingFlags.Public ||| BindingFlags.NonPublic
        let fields = objectType.GetFields (flags) |> Seq.cast<MemberInfo> |> Seq.toArray
        fields |> Array.append (objectType.GetProperties (flags) |> Array.filter (fun propInfo -> propInfo.CanWrite) |> Seq.cast<MemberInfo> |> Seq.toArray) |> ResizeArray
    override this.CreateProperties(t : Type, _ : MemberSerialization) = 
        base.CreateProperties (t, MemberSerialization.Fields)

module Foo =

  let deserialize str =
      let settings = JsonSerializerSettings()
      settings.ContractResolver <- PrivateContractResolver()
      let r = Newtonsoft.Json.JsonConvert.DeserializeObject<Foo>(str, settings)
      r.Bar

[<EntryPoint>]
let main _ =
    let result = Foo.deserialize """
{ 'Bar': 'Hi' }
"""
    printfn "%s" result
    0