F#: Как получить доступ к элементам перечисленным способом из файла JSON?


Мне нравятся поставщики типов F#, и именно поэтому я стараюсь использовать FSharp.Библиотека данных, когда я могу, но я нашел вариант использования,который не кажется покрытым.

Рассмотрим этот простой файл JSON:

{
    "Foo": {
        "Baz": 0,
        "Bazz": "x"
    },
    "Bar": {
        "Baz": 10,
        "Bazz": "y"
    }
}

Я хочу разобрать элементы выше как массив, а не обращаться к элементам Foo и Bar жестко. То есть, получая IEnumerable<SomeRecord>, где SomeRecord имеет 2 члена Baz и Bazz. Можно ли каким-то образом использовать API JsonProvider для достижения этой цели?

Я попробовал SampleIsList=true вариант, но, кажется, не работает:

type MyJsonProvider = JsonProvider<"./elements.json",
                                   EmbeddedResource="MyAssemblyName, elements.json",
                                   SampleIsList=true>

let SomeReadingMethod() =
    let assembly = Assembly.GetExecutingAssembly()
    let embeddedServerListFileName = "elements.json"
    use stream = assembly.GetManifestResourceStream(embeddedServerListFileName)
    use reader = new StreamReader(stream)
    let list = reader.ReadToEnd()

    let elements = MyJsonProvider.Parse(list)
    for element in elements do
        ...

Я получаю ошибку компилятора: The type JsonProvider<...>.Root is not a type whose values can be enumerated with this syntax...

1 3

1 ответ:

Можно ли каким-то образом использовать API JsonProvider для достижения этой цели?

Нет, вводимый вами пример-этоКарта от ключей/полей до значений, а не перечисление значений. SampleIsList предназначен для случаев, когда сам образец представляет собой коллекцию, содержащую несколько экземпляров типа, который вы предполагаете. Если вы хотите использовать JsonProvider с этим, я думаю, вам нужно будет изменить свою схему JSON как во время разработки, так и во время выполнения.

В качестве альтернативы я бы рассмотрел написание простого синтаксического анализатора, либо с использованием функций JSON parsing в FSharp.Data или одна из других библиотек синтаксического анализа OSS F# JSON. Вот рудиментарный пример:

open FSharp.Data
open FSharp.Data.JsonExtensions

let info =
  JsonValue.Parse(""" 
    {
    "Foo": {
        "Baz": 0,
        "Bazz": "x"
    },
    "Bar": {
        "Baz": 10,
        "Bazz": "y"
    }
} """)
type MyRecord = {
  Baz : int;
  Bazz : string
}
let parse props =
  seq {
    for (_k,v) in props ->
      {Baz = v?Baz.AsInteger(); Bazz = v?Bazz.AsString()}
  }

> parse info.Properties;;
val it : seq<MyRecord> =
  seq [{Baz = 0; Bazz = "x";};
       {Baz = 10; Bazz = "y";}]