IgnoreMissingMember设置似乎不适用于FSharpLu.Json反序列化器 [英] IgnoreMissingMember setting doesn't seem to work with FSharpLu.Json deserializer

查看:134
本文介绍了IgnoreMissingMember设置似乎不适用于FSharpLu.Json反序列化器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是以下内容:反序列化问题,带有json.net,位于F#

我正在使用 FSharpLu.Json 。下面是代码:

I am deserializing some JSON that has an extra, unbound property using FSharpLu.Json. Here is the code:

open System
open Newtonsoft.Json
open Microsoft.FSharpLu.Json

type r =
    {
        a: int
    }

let a =
    "{\"a\":3, \"b\":5}" 

Compact.TupleAsArraySettings.settings.MissingMemberHandling <- MissingMemberHandling.Ignore
Compact.deserialize<r> a  // doesn't work

尽管设置 MissingMemberHandling.Ignore 返回json.net错误:

Despite setting MissingMemberHandling.Ignore it returns a json.net error:


在类型为'r'的对象上找不到成员'b'。路径'b',第1行,位置13。

Could not find member 'b' on object of type 'r'. Path 'b', line 1, position 13.

有没有办法使此工作有效,或者FSharpLu是否有问题杰森?

Is there a way to make this work, or is it an issue with FSharpLu.Json?

这是小提琴: https:// dotnetfiddle .net / OsVv1M

作为一个注释,FSharpLu中还有另一个反序列化器。Json,我可以使用该代码来对其进行处理:

as a side note, there is another deserializer in FSharpLu.Json and I can get that code to work with it:

FSharpLu.Json.Default.Internal.DefaultSettings.settings.MissingMemberHandling <- MissingMemberHandling.Ignore
Default.deserialize<r> a

可以工作,但是该反序列化器不能处理歧视的工会...所以我需要

will work, but that deserializer doesn't handle discriminated unions... so I need to get the compact one to work.

当研究FSharpLu.Json的来源时,我发现了这一点:

When looking into the source of FSharpLu.Json, I found this:

/// Compact serialization where tuples are serialized as heterogeneous arrays
type TupleAsArraySettings =
    static member formatting = Formatting.Indented
    static member settings =
        JsonSerializerSettings(
            NullValueHandling = NullValueHandling.Ignore,

            // MissingMemberHandling is not technically needed for
            // compact serialization but it avoids certain ambiguities
            // that guarantee that deserialization coincides with the
            // default Json.Net deserialization.
            // (where 'coincides' means 'if the deserialization succeeds they both return the same object')
            // This allows us to easily define the BackwardCompatible
            // serializer (that handles both Compact and Default Json format) by reusing
            // the Compact deserializer.
            MissingMemberHandling = MissingMemberHandling.Error,
            Converters = [| CompactUnionJsonConverter(true, true) |]
        )

所以他们明确地将MissingMemberHandling设置为错误;也许解决方案是实例化反序列化器,更改设置然后使用它。

so they are explicitly setting the MissingMemberHandling to Error; maybe the solution is to instantiate the deserializer, change the setting and then use it.

推荐答案

您要更改的序列化器设置 Compact.TupleAsArraySettings.settings 静态成员,如代码

The serializer setting you are trying to mutate, Compact.TupleAsArraySettings.settings, is a static member, as is shown in the code:


type TupleAsArraySettings =
    static member formatting = Formatting.Indented
    static member settings =
        JsonSerializerSettings(
            NullValueHandling = NullValueHandling.Ignore,

            // MissingMemberHandling is not technically needed for
            // compact serialization but it avoids certain ambiguities
            // that guarantee that deserialization coincides with the
            // default Json.Net deserialization.
            // (where 'coincides' means 'if the deserialization succeeds they both return the same object')
            // This allows us to easily define the BackwardCompatible
            // serializer (that handles both Compact and Default Json format) by reusing
            // the Compact deserializer.
            MissingMemberHandling = MissingMemberHandling.Error,
            Converters = [| CompactUnionJsonConverter(true, true) |]
        )


由于成员实际上是成员函数(即方法),如 获得乐趣和收益的F#:将函数附加到类型 设置实际上(使用C#术语)静态属性,每次调用时都会返回 JsonSerializerSettings 的新实例。要对此进行测试,我们可以这样做:

Since a member is actually a member function (i.e. a method) as explained F# for fun and profit: Attaching functions to types, settings is actually (in c# terminology) a static property returning a new instance of JsonSerializerSettings each time it is invoked. To test this, we can do:

printfn "%b" (Object.ReferenceEquals(Compact.TupleAsArraySettings.settings, Compact.TupleAsArraySettings.settings)) // prints "false"

其中哪个打印假。因此,更改返回的值不会影响 Compact 的行为。 c#意义上的静态字段将由 static let 语句定义;如果 settings 返回这样的字段,则对其内容进行更改将产生效果。

Which prints "false". Thus mutating the returned value has no effect on the behavior of Compact. A static field in the c# sense would be defined by a static let statement; if settings returned such a field, mutating its contents would have had an effect.

无论如何修改 Compact.TupleAsArraySettings.settings.MissingMemberHandling 的值似乎都不明智,因为这样做会修改在整个AppDomain中 Compact.deserialize 的行为可能会破坏与Json.NET本机序列化的向后兼容性。如上述代码注释中所述,必须进行设置才能使 BackwardCompatible.deserialize 工作。但是为什么会这样呢?由于Json.NET的选项的本机格式和有区别的联合看起来像:

In any event modifying the value of Compact.TupleAsArraySettings.settings.MissingMemberHandling seems unwise as doing so would modify the behavior of of Compact.deserialize throughout your entire AppDomain in a way that might break backwards compatibility with Json.NET native serialization. As explained in the code comments above, the setting is required to make BackwardCompatible.deserialize work. But why might that be? Since Json.NET's native format for option and discriminated unions looks like:

{
  "a": {
    "Case": "Some",
    "Fields": [
      3
    ]
  }
}

我们可以猜测 MissingMemberHandling 是用于捕获未找到 Case Fields 的情况,并从一种算法切换到其他。

We can guess that MissingMemberHandling is used to trap situations where "Case" and "Fields" are found or not, and switch from one algorithm to the other.

如果您确定不需要反序列化Json.NET格式的f#类型,看来您应该可以使用 CompactUnionJsonConverter 直接如下:

If you are certain you do not need to deserialize f# types in Json.NET format, it seems you should be able to use CompactUnionJsonConverter directly as follows:

let settings = JsonSerializerSettings(
    NullValueHandling = NullValueHandling.Ignore,
    Converters = [| CompactUnionJsonConverter(true, true) |]
)
let c = JsonConvert.DeserializeObject<r>(a, settings)
let json2 = JsonConvert.SerializeObject(c, Formatting.Indented, settings)

演示小提琴此处

这篇关于IgnoreMissingMember设置似乎不适用于FSharpLu.Json反序列化器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆