F# 和 Web API Json 用于在 DataFrame 中进行分析

F# and Web API Json for analysis in DataFrame

我正在尝试通过重写 python 中的一些脚本来学习 F#,我在其中查询 graphql 端点并将 json 加载到 Pandas DataFrame 中以进行清理和分析:

json 像这样:

apiResponse = {"data":
                    {"Shipments":{"ErrorMessage":null,
                    "Success":true,
                    "ValidationResult":null,
                    "TotalCount":494,
                    "Data":[
                       {"Building":"B7",
                        "Comment":"Test",
                        "CompletedDate":"2021-04-12T10:13:13.436Z",
                        "ItemId":"dd4520bb-aa0a-...",
                        "NoOfUnit":5,
                        "Organization":{
                              "OrganizationId":"cac43a32-1f08-...",
                              "OrganizationName":"XXX"},
                       "Adress":"Road 5"
                      },
                      {"Building":"B7",
                      ....}]}}}

Python:

data = request.json()
#only the "Data" path
json_list = data['data']['Shipments']['Data']
df = json_normalize(json_list)

与使用 Fsharp.Data 相同的方法,而“file.json”只是“Data[]”部分(我试图创建一个 fiddle,但我无法获取它到 运行。here:


type ApiTypes = JsonProvider<"file.json"> //where file.json has only "Data" path of apiResponse
let jsonResponse = JsonValue.Parse(apiResponse)
let data = jsonResponse?data
let Shipments = data?Shipments
let Data = Shipments?Data

let input = 
 ApiTypes.Parse(Data.ToString())

let df = Frame.ofRecords input

但这不起作用。 所以我的问题:

  1. 这是使用此 json 的正确方法吗?
  2. 是否有更好的方法来使用 json 创建 DataFrame?

感谢任何帮助。 谢谢

我没有任何使用 Deedle 的经验,但我认为 ofRecords 可以正常工作,因此它可能与 JsonProvider 不兼容。 (至少我无法让它工作。)

相反,我会手动定义类型,然后反序列化为它,如下所示:

open Newtonsoft.Json.Linq

type Datum =
    {
        Building : string
        Comment : string
        CompletedDate : DateTime
        ItemId : Guid
        NoOfUnit : int
        Organization :
            {|
                OrganizationId : Guid
                OrganizationName : string
            |}
        Adress : string
    }

let jobj = JObject.Parse(apiResponse)
let frame =
    jobj.["data"].["Shipments"].["Data"].Children()
        |> Seq.map (fun jtok -> jtok.ToObject<Datum>())
        |> Frame.ofRecords