F# 将 JSON 字符串反序列化为正确的记录类型
F# deserialize a JSON string into correct record type
场景是 - 从网络接收 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)
最后一行returns一个对象类型的对象。
对其使用模式匹配并不能确定类型:
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"
此处打印 "None of above"。
当我使用指示某种类型反序列化对象时:
JsonConvert.DeserializeObject<Type1>(someJsonString)
模式匹配正在运行并正在打印:
Type1: a = <the value of a>
但是,这在我的情况下不起作用,因为我无法提前知道未知 JSON 字符串的内容类型。
有什么方法可以根据字符串内容将 JSON 字符串反序列化为正确的记录类型吗?
注意:如有必要,当字符串在发送端被序列化时,类型的名称可以作为该字符串的一部分发送。但是,如何获取 Type 类型的实例,具有类型名称,如 "Type1" 或 "Type2"?
类型的完全限定名称在不同的机器上会有所不同,所以我不确定是否可行。 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 字符串并将其反序列化为正确的相应记录类型。
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)
最后一行returns一个对象类型的对象。
对其使用模式匹配并不能确定类型:
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"
此处打印 "None of above"。
当我使用指示某种类型反序列化对象时:
JsonConvert.DeserializeObject<Type1>(someJsonString)
模式匹配正在运行并正在打印:
Type1: a = <the value of a>
但是,这在我的情况下不起作用,因为我无法提前知道未知 JSON 字符串的内容类型。
有什么方法可以根据字符串内容将 JSON 字符串反序列化为正确的记录类型吗?
注意:如有必要,当字符串在发送端被序列化时,类型的名称可以作为该字符串的一部分发送。但是,如何获取 Type 类型的实例,具有类型名称,如 "Type1" 或 "Type2"?
类型的完全限定名称在不同的机器上会有所不同,所以我不确定是否可行。 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)