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

问题描述 投票:3回答:1

我喜欢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...

json f# f#-data
1个回答
3
投票

是否有可能以某种方式使用JsonProvider API来实现这一目标?

不,您提供的示例输入是从键/字段到值的映射 - 而不是值的枚举。 SampleIsList适用于您的样本本身是一个包含您所推断类型的多个实例的集合。如果你想使用JsonProvider,我认为你需要在设计和运行时改变你的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";}]
© www.soinside.com 2019 - 2024. All rights reserved.