2014-06-12 56 views
4

我正在學習類型提供程序,它看起來像一個突破性功能。但是,我無法設法使用JsonProvider對json進行反序列化,以便目標類型具有Generic.Dictionary屬性。它可以用Json.NET完成。下面是代碼:可以JsonProvider反序列化到Generic.Dictionary?

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默認。這可以重寫嗎?

回答

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類型提供者可以擴展以更好地處理這個問題(並且將對象記錄更像數組)。隨意提交問題討論&也許提交一個請求到F# Data on GitHub

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