【问题标题】:Can JsonProvider deserialise to a Generic.Dictionary?JsonProvider 可以反序列化为 Generic.Dictionary 吗?
【发布时间】:2014-06-12 11:01:06
【问题描述】:

我正在学习类型提供程序,它看起来像是一个开创性的功能。但是,我无法使用 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。可以覆盖吗?

【问题讨论】:

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


    【解决方案1】:

    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 类型提供程序可以扩展以更好地处理这个问题(并将记录更像数组处理)。随时提交问题以供讨论,也可以向F# Data on GitHub 提交拉取请求!

    【讨论】:

      【解决方案2】:

      如果要将 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&lt;string,JsonValue&gt;。如果你希望它是整数,你可以在中间使用Seq.map

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

      【讨论】:

        猜你喜欢
        • 2010-09-23
        • 2018-06-21
        • 1970-01-01
        • 2011-12-30
        • 2022-01-20
        • 1970-01-01
        • 2013-02-22
        • 1970-01-01
        相关资源
        最近更新 更多