简体   繁体   English

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

[英]Deserializing private types in F# with Newtonsoft.Json

When working with Newtonsoft.Json, how do you deserialize private types?使用 Newtonsoft.Json 时,如何反序列化私有类型? For example:例如:

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

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

This sounds rather unusual, but I'll assume you have a good reason to use a private type.这听起来很不寻常,但我假设您有充分的理由使用私有类型。

The problem here is that Json.NET cannot see the any public properties on the type, you can fix this by using a custom contract resolver and tell it to find the private members.这里的问题是 Json.NET 看不到类型上的任何公共属性,您可以通过使用自定义合同解析器并告诉它查找私有成员来解决此问题。

Like this:像这样:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM