将JSON扩展为deedle数据帧的collums

时间:2018-01-14 17:06:17

标签: json f#-data deedle

我试图将JSON从网站转换为deedle数据帧,将JSON条目扩展到数据框的单独列。我找到了this discussion,但我无法让建议的解决方案适合我。由于我是JSON和deedle的新手,我可能会犯一个愚蠢的错误。我尝试了以下内容(主要是从引用的讨论中复制而来):

let rec expander key value =
    seq {
        match value with
        | JsonValue.String  (s) -> yield key,typeof<string>,box s
        | JsonValue.Boolean (b) -> yield key,typeof<bool>,box b
        | JsonValue.Float   (f) -> yield key,typeof<float>,box f
        | JsonValue.Null    (_) -> yield key,typeof<obj>,box ()
        | JsonValue.Number  (n) -> yield key,typeof<decimal>,box n
        | JsonValue.Record  (r) -> yield! r |> Seq.collect ((<||)expander)
        | JsonValue.Array   (a) ->
            yield! a
            |> Seq.collect (expander "arrayItem")
    }

Frame.CustomExpanders.Add(typeof<JsonDocument>,
                          fun o -> (o :?> JsonDocument).JsonValue |> expander "root")

Frame.CustomExpanders.Add(typeof<JsonValue>,
                          fun o -> o :?> JsonValue |> expander "root")

let info =
    JsonValue.Parse(""" { "name": "Tomas", "born": 1985 } """)

let df =
    [ series ["It" => info] ]
    |> Frame.ofRowsOrdinal

let dfexpanded = Frame.expandAllCols 2 df

这给了我一些我不知道如何解释的东西,但不是所希望的结果:

It.properties                                         It.Tag It.IsString It.IsNumber It.IsFloat It.IsRecord It.IsArray It.IsBoolean It.IsNull It._Print                             
0 -> System.Tuple`2[System.String,FSharp.Data.JsonValue][] 3      False       False       False      True        False      False        False     { "name": "Tomas", "born": 1985 } 

我感谢任何意见!

1 个答案:

答案 0 :(得分:1)

问题似乎是数据框中It的类型不是JsonValue,而是编译器生成的一个子类,用于表示受歧视联合的个别情况 - 在这种特殊情况,是一个名为JsonValue+Record的嵌套类型。

Deedle查找确切的类型匹配(并且不会尝试为基类找到扩展器),因此解决方法是为每个嵌套类注册扩展器:

for t in typeof<JsonValue>.GetNestedTypes() do
  Frame.CustomExpanders.Add(t, fun o -> o :?> JsonValue |> expander "root")

运行此代码后,您的代码会给出预期的结果:

val dfexpanded : Frame<int,string> =

     It.name It.born 
0 -> Tomas   1985