【问题标题】:F# deserialize a JSON string into correct record typeF# 将 JSON 字符串反序列化为正确的记录类型
【发布时间】:2017-01-22 00:56:38
【问题描述】:

场景是 - 从网络接收 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”?

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

【问题讨论】:

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


    【解决方案1】:

    如果没有额外的类型信息,您一般无法做到这一点。序列化时需要指定类型,以便在反序列化时可以读回。

    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)
    

    【讨论】:

    • 如果对象在一台机器上被序列化,而在另一台机器上反序列化,这将不起作用。例如,我在一台机器上尝试过——它可以将对象反序列化为正确的类型。但是如果你在不同的机器上反序列化它,完全限定的类型名称是不同的,因为它的前缀是“FSI_0047+Type1”的不同变体。您知道如何确保每次运行相同类型具有相同的完全限定程序集名称吗?
    • 这是因为您使用的是 FSI。生成类型名。否则,在两台机器之间共享一个程序集并使用#r 引用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    相关资源
    最近更新 更多