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

时间:2017-01-22 00:56:38

标签: 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字符串反序列化为正确的记录类型?

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

该类型的完全限定名称在不同的机器上会有所不同,所以我不确定它是否可行。即一台机器将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"

1 个答案:

答案 0 :(得分:2)

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

序列化时,

Newtonsoft.JsonTypeNameHandling 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)