2013-04-02 4 views
1

Мне нужно прочитать в некоторых данных из файла, который хранится как массивы JSON. В основном данные представляют собой двоичное дерево с метками для узлов и значениями на листах, а стилизованная строка выглядит так:F # десериализующий массив массивов

[label1, [label2, [label3, w], x], [label4, y, z] ]

с произвольными уровнями глубины на всех ветвях. Теперь в конечном счете, я ищу, чтобы превратить это в древовидную структуру, но первый шаг читает его в

Следующая C# код работает (с использованием System.Web.Extensions.dll).

var jss = new JavaScriptSerializer(); 
foreach (string line in System.IO.File.ReadAllLines(filename)) 
{ 
    var data = jss.Deserialize<object[]>(line); 
} 

С «работами» я имею в виду, что на приведенном выше примере данные. [1] снова представляет собой массив объектов. Прямой порт для F # равен

let data = 
    let jss = new JavaScriptSerializer() 
    System.IO.File.ReadAllLines(filename) 
     |> Seq.map (fun line -> jss.Deserialize<obj[]>(line)) 

Однако применение этого к примеру приводит к данным. [1] являясь объектом, а не массивом объектов.

Я считал замену десериализации на

 |> Seq.map (fun line -> jss.Deserialize<seq<obj[]>(line)) 

но не работает (в моем примере) label1 является строкой и (очевидно) не могут быть преобразованы в System.Object []. Я также попробовал обернуть код C# в статическом классе, а затем использовать этот класс для чтения в данных в F #, но это тоже не работает. Я знаю, что я могу использовать внешний JSON-парсер, но поскольку использование JavaScriptSerializer действительно работает на C#, мой stubborness пинает, и я тоже хотел бы сделать это в F #. Какие-либо предложения?

+0

Возможно, вы можете использовать [JSON Type Provider] (http://fsharp.github.com/FSharp.Data/library/JsonProvider.html) для реализации этого? –

ответ

3

Это работает для меня:

#r "System.Web.Extensions" 

open System.Web.Script.Serialization 

let jss = new JavaScriptSerializer() 
let data = jss.Deserialize<obj[]>("""["label1",["label2",["label3","w"],"x"],["label4","y","z"]]""") 
let doesItWork = data.[1].GetType() = typeof<obj[]> 

могли бы вы предоставить более полный пример того, что не работает для вас?

+0

ПК, к которому у меня есть доступ прямо сейчас, не поддерживает F # 3.0, поэтому строка с тройным цитированием не работает для меня. Однако для меня 'data. [1] .GetType() = typeof ' также возвращает true, но в то же время что-то вроде '(data. [1]). [0]' не работает, altough '(data. [1]:?> obj []). [0] 'делает. Отметить это как ответ, так как я прохожу через оставшуюся часть данных, но не уверен, что понимаю разницу в поведении против C#. – Bram

+0

@Bram - Я удивлен, что ваш код на C# тоже не нуждается в соответствующем приведении (если вы не используете 'dynamic' где-то). – kvb

+0

Я не использовал '' dynamic'' в своем коде C# где угодно. Во всяком случае, то, что я хотел работать, теперь работает, и пока я не собираюсь заниматься тем, что вызывает разницу: слишком мало времени и слишком мало знаний о MSIL, чтобы сравнить их. Спасибо за вашу помощь. – Bram

Смежные вопросы