IgnoreMissingMember设置似乎不适用于FSharpLu.Json反序列化器 [英] IgnoreMissingMember setting doesn't seem to work with FSharpLu.Json deserializer
问题描述
这是以下内容:反序列化问题,带有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屋!