F#:如何从 JSON 文件中以枚举方式访问元素?

F#: how to access elements in an enumerated way from JSON file?

我喜欢 F# 类型提供程序,这就是为什么我尽可能尝试使用 FSharp.Data 库,但我发现了一个似乎没有涵盖的用例。

考虑这个简单的 JSON 文件:

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

我想将上面的元素解析为数组,而不是以硬编码方式访问 Foo 和 Bar 的元素。也就是说,接收一个 IEnumerable<SomeRecord>,其中 SomeRecord 有 2 个成员 BazBazz。是否可以通过某种方式使用 JsonProvider API 来实现这一点?

我尝试了 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...

Is it possible to use JsonProvider API in some way to achieve this?

不,您提供的示例输入是从 keys/fields 到值的 map,而不是值的枚举。 SampleIsList 适用于当您的样本本身是一个包含您正在推断的类型的多个实例的集合时。如果您想将 JsonProvider 与此一起使用,我认为您将需要在设计和 run-time.

中更改您的 JSON 架构

或者,我会考虑编写一个简单的解析器,使用 JSON parsing features in 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";}]