【发布时间】:2020-10-04 05:12:42
【问题描述】:
以下问题的答案提供了一个有效的解决方案来序列化/反序列化受歧视的联合 (IgnoreMissingMember setting doesn't seem to work with FSharpLu.Json deserializer)
我现在有一个失败的实际案例(尽管它适用于更简单的情况)。
这里是测试代码:
open System.Collections.Generic
open Microsoft.FSharpLu.Json
open Newtonsoft.Json
open Newtonsoft.Json.Serialization
// set up the serialization / deserialization based on answer from:
// https://stackoverflow.com/questions/62364229/ignoremissingmember-setting-doesnt-seem-to-work-with-fsharplu-json-deserializer/62364913#62364913
let settings =
JsonSerializerSettings(
NullValueHandling = NullValueHandling.Ignore,
Converters = [| CompactUnionJsonConverter(true, true) |]
)
let serialize object =
JsonConvert.SerializeObject(object, settings)
let deserialize<'a> object =
JsonConvert.DeserializeObject<'a>(object, settings)
// define the type used
type BookSide =
| Bid
| Ask
type BookEntry =
{
S : float
P : float
}
type BookSideData =
Dictionary<int, BookEntry>
type BookData =
{
Data: Dictionary<BookSide, BookSideData>
}
static member empty =
{
Data = Dictionary<BookSide, BookSideData>(dict [ (BookSide.Bid, BookSideData()); (BookSide.Ask, BookSideData()) ])
}
// make some sample data
let bookEntry = { S=3.; P=5. }
let bookData = BookData.empty
bookData.Data.[BookSide.Bid].Add(1, bookEntry)
// serialize. This part works
let s = serialize bookData
// deserialize. This part fails
deserialize<BookData> s
序列化的测试数据将如下所示:
{"Data":{"Bid":{"1":{"S":3.0,"P":5.0}},"Ask":{}}}
但是反序列化会像这样崩溃:
无法将字符串“Bid”转换为字典键类型“FSI_0023+BookSide”。创建一个 TypeConverter 将字符串转换为键类型对象。
虽然通过具有DU转换器的FSharpLu对DU进行序列化/反序列化。
与编写自定义 TypeConverter 相比,我试图找到一些自动化解决方案的原因(除了我从未这样做过)是因为我有很多我无法控制的类型。
这是一个小提琴: https://dotnetfiddle.net/Sx0k4x
【问题讨论】:
-
你的
BookSide是一个联合,它使它成为一个复杂的键——不能立即转换为字符串。 Json.NET 不支持开箱即用的字典的复杂键,请参阅Not ableTo Serialize Dictionary with Complex key using Json.net。如果你让BookSide成为一个枚举而不是一个联合(type BookSide = | Bid=1 | Ask=2)那么一切似乎都正常工作:dotnetfiddle.net/xBOytT。如果你将printfn "%s" s添加到你自己的小提琴中,你会发现字典键是无意义的ToString()值。 -
不幸的是我不控制这些类型,所以我不能将它们移动到枚举中;我有 30 多个对象都使用 DU 来处理:/这就是我寻找通用解决方案的原因
-
那么你需要将这样的字典序列化为数组,见Serialize dictionary as array (of key value pairs)。或者你可以为你的工会写一个
TypeConverter,见Not ableTo Serialize Dictionary with Complex key using Json.net。这些是否充分回答了您的问题,还是您需要更多帮助? -
无论哪种方式,无法序列化具有复杂键的字典是 Json.NET 的一个明确限制,请参阅It's currently not possible to deserialize dictionaries with complex classes as keys. #516。
-
另外,你的字典键总是enum-like unions吗?
标签: serialization f# json.net deserialization discriminated-union