f# - 反序列化为 F# 中的枚举选项
问题描述
几天前,我发布了一个关于在 F# 中使用枚举进行反序列化的问题。问题就在这里:F# 与 C# 中的反序列化
答案指向了 Isaac Abraham 编写的一些代码,位于:https ://gist.github.com/isaacabraham/ba679f285bfd15d2f53e
但是我面临另一个问题:
如果要反序列化的对象具有“枚举选项”类型的对象,则反序列化将失败,而如果类型只是“枚举”,它将起作用。
一个最小的例子:
type TestType =
| A = 0
| B = 1
type TestObjectA =
{
test : TestType
}
type TestObjectB =
{
test : TestType option
}
let x = "{\"test\":\"A\"}"
let TestA = Deserialize<TestObjectA> x // will work
let TestB = Deserialize<TestObjectB> x // will fail
大型反序列化代码位于:https ://pastebin.com/95JZLa6j
我把整个代码放在一个小提琴中:https ://dotnetfiddle.net/0Vc0Rh 但它不能从那里运行,因为他们支持的 F# 版本不接受'object'关键字。
所以,我的问题是:为什么我不能在枚举上使用选项类型,但它适用于其他类型?附带说明一下,由于我对 F# 还很陌生,所以我并没有完全理解 Isaac 的代码,尽管我花了一些时间来研究它并尝试对其进行故障排除。
我的理解是这一行:|> Seq.map (fun (value, propertyInfo) -> Convert.ChangeType(value, propertyInfo.PropertyType))
将尝试将类型转换为正确的枚举,而不是枚举选项。
作为一个额外的问题,是否有一个可行的解决方案可以使用枚举进行完全惯用的反序列化?(不经过空类型)
解决方案
open System.IO
type TestType =
| A = 0
| B = 1
type TestObjectB =
{
test : TestType option
}
let jsonSerializeToString obj =
use writer = new StringWriter()
let ser = new Newtonsoft.Json.JsonSerializer()
ser.Formatting <- Newtonsoft.Json.Formatting.Indented
ser.Serialize(writer, obj)
writer.ToString()
let jsonDeserializeFromString str =
Newtonsoft.Json.JsonConvert.DeserializeObject<TestObjectB>(str)
let Test obj =
let str = jsonSerializeToString obj
let obj' = jsonDeserializeFromString str
obj'
[<EntryPoint>]
let main argv =
{ test = Some TestType.B } |> Test |> ignore
{ test = None } |> Test |> ignore
0
注意:如果您需要序列化大量对象集合,请将它们流式传输到文件而不是内存中的字符串以避免 OutOfMemoryException。喜欢use writer = File.CreateText(filePath)
。
推荐阅读
- ios - UIPageViewController 不调用委托方法(Swift 5)
- javascript - javascript中var和函数的区别
- typescript - 扁平化函数的 TypeScript 类型定义
- sql-server - 在派生列中嵌套 IF ELSE
- python - 模型不可行或无界使用 python Gurobi
- php - 使用 PHP 检查 txt 文件中的电子邮件是否存在
- c++ - 未解析的外部符号 _MsiLocateComponentW@12
- reactjs - 如何在钩子上扩展 React 功能组件?
- angular - 如何在单页网站 Angular 9 中管理路由
- r - RStudio“运行文档”不生成html文件