Может ли JsonProvider десериализоваться в Generic.Dictionary?

Я изучаю поставщиков типов, и это похоже на новаторскую функцию. Однако мне не удается десериализовать json с помощью JsonProvider, чтобы у целевого типа было свойство 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. Можно ли это переопределить?


person Arbil    schedule 12.06.2014    source источник


Ответы (2)


Поставщик типа 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 на GitHub!

person Tomas Petricek    schedule 12.06.2014

Если вы хотите преобразовать словарь 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
person pqnet    schedule 20.06.2016