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

时间:2018-03-04 10:31:41

标签: json f# f#-data

我喜欢F#类型的提供商,这就是我尽可能尝试使用FSharp.Data库的原因,但我发现了一个似乎无法覆盖的用例。

考虑这个简单的JSON文件:

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

我想将上面的元素解析为数组,而不是以硬编码的方式访问Foo&Bar和s的元素。也就是说,收到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...

1 个答案:

答案 0 :(得分: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";}]
相关问题