json - F# 将 JSON 字符串反序列化为正确的记录类型

标签 json serialization f# json-deserialization json-serialization

场景是 - 从网络接收 JSON 字符串并将其反序列化为正确的对应记录类型。

JSON 字符串可以是:

(1) "{"a":"some text"}"

(2) "{"b":1}"

值可能不同,但字段的格式将对应于 Type1 或 Type2:

type Type1 = {a:string}
type Type2 = {b:int}

当收到未知字符串时,我尝试获取正确记录类型的实例:

// Contents of a string might be like (1) or like (2), but we don't know which one
let someJsonString = "..."

let obj = JsonConvert.DeserializeObject(someJsonString)

最后一行返回一个 Object 类型的对象。

对其使用模式匹配并不能确定类型:

match obj with
| :? Type1 as t1 -> printfn "Type1: a = %A" t1.a
| :? Type2 as t2 -> printfn "Type2: b = %A" t2.b
| _ -> printfn "None of above"

这里打印了“以上都不是”。

当我使用指示某种类型反序列化对象时:

JsonConvert.DeserializeObject<Type1>(someJsonString)

模式匹配正在工作并正在打印:

Type1: a = <the value of a>

但是,这对我来说不起作用,因为我无法提前知道未知 JSON 字符串将具有什么类型的内容。

有没有办法根据字符串内容将 JSON 字符串反序列化为正确的记录类型?

注意:如有必要,当字符串在发送端序列化时,类型名称可以作为该字符串的一部分发送。但是,如何获取具有类型名称(例如“Type1”或“Type2”)的 Type 类型的实例?

类型的完全限定名称在不同的机器上会有所不同,所以我不确定是否可能。 IE。一台机器将 Type1 指定为:

"FSI_0059+Test1, FSI-ASSEMBLY, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"

另一个是:

"FSI_0047+Test1, FSI-ASSEMBLY, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"

最佳答案

如果没有附加类型信息,您通常无法执行此操作。序列化时需要指定类型,以便反序列化时可以读回它。

Newtonsoft.Json 有一个 TypeNameHandling option that you can set序列化时,以便将生成的 JSON 反序列化为正确的类型。

这是一个完整的示例:

let instance = { a = 10 }
let settings = new JsonSerializerSettings(TypeNameHandling = TypeNameHandling.All)
let json = JsonConvert.SerializeObject(instance, settings)
let retrieved = JsonConvert.DeserializeObject(json, settings)

关于json - F# 将 JSON 字符串反序列化为正确的记录类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41786237/

相关文章:

从 Boost object_pool 构造的指针的 C++ Boost 二进制序列化

json - 检查 fetch_json sub 中的 HTTP 代码/保存以前的输出以在 Perl 中进行备份

json - 如何用 json 存储 Protocol Buffer 的 "oneof"字段

javascript - 无法在 javascript 脚本标记内输出实际的 json 数据

javascript - 如何将参数传递给 JQuery $.getJSON 回调方法?

c# - WIN RT 中是否存在二进制序列化程序?

JAVA序列化和反序列化: Of two separate objects that have their own array lists under one file

f# - 在 akka.net actor{} 表达式中等待 F# 异步任务

f# - F# 的 Web 项目

f# - 创建仅对 F# 项目可见的模块/类型