Json Provider可以反序列化为Generic.Dictionary吗?

时间:2014-06-12 11:01:06

标签: f# type-providers f#-data

我正在学习类型提供程序,它看起来像是一个突破性的功能。但是,我无法使用JsonProvider对json进行反序列化,以便目标类型具有Generic.Dictionary属性。它可以用Json.NET完成。这是代码:

type ByProv = JsonProvider<"""{"dict":{"A":1,"B":2}}""">
type ByHand(d:Dictionary<string,int>) =
    member val dict = d with get,set

let text = """{"dict":{"C":3,"D":4}}"""
let newt = JsonConvert.DeserializeObject<ByHand> text
let prov = ByProv.Parse text
printfn "%A" newt.dict.["C"]
//Can only call statically inferred A or B (and it will throw at run-time)
printfn "%A" prov.Dict.A

显然,dict被推断为记录类型,默认情况下不是Dictionary。可以覆盖吗?

2 个答案:

答案 0 :(得分:4)

JSON类型提供程序假定JSON记录用于存储记录(具有固定字段名称),并且JSON数组用于存储集合。你的例子就是其中一个不能很好用的情况之一。

当您需要访问具有动态命名字段的JSON记录时,您可以使用由提供的类型公开的基础JsonValue

type ByProv = JsonProvider<"""{"dict":{"A":1,"B":2}}""">

let text = """{"dict":{"C":3,"D":4}}"""
let prov = ByProv.Parse text

prov.Dict.JsonValue.["C"].AsInteger()

这不是很好,我想可以扩展JSON类型提供程序以更好地处理它(并将记录更像数组)。随意提交问题进行讨论&amp;或者向F# Data on GitHub提交拉取请求!

答案 1 :(得分:0)

如果要将JSON字典转换为.net字典,可以使用Properties()方法和dict函数,如下所示:

type ByProv = JsonProvider<"""{"dict":{"A":1,"B":2}}""">

let text = """{"dict":{"C":3,"D":4}}"""

let prov = ByProv.Parse text

let d = prov.Dict.JsonValue.Properties() |> dict

d的类型为System.Collections.Generic.IDictionary<string,JsonValue>。如果你想要它是整数,你可以在中间使用Seq.map

let d =
    prov.Dict.JsonValue.Properties()
    |> Seq.map (fun (k,v) -> k,v.AsInteger())
    |> dict