F# 数据 JSON 类型提供程序:如何处理可以是数组或 属性 的 JSON 属性?

F# Data JSON type provider: How to handle a JSON property that can be an array or a property?

我正在使用 F# 数据库中的 JSON 类型提供程序来访问 API 中的 JSON 文档。这些文档包含一个 属性(我们称之为 'car'),它有时是一个对象数组,有时是单个对象。要么是这样:

'car': [
  { ... },
  { ... }
]

或者这个:

'car': { ... }

{ ... }中的对象在两种情况下具有相同的结构。

JSON 类型提供程序表示 属性 的类型为:

JsonProvider<"../data/sample.json">.ArrayOrCar

其中 sample.json 是我的示例文档。

然后我的问题是:如何确定 属性 是数组(以便我可以将其作为数组处理)还是单个对象(以便我可以将其作为对象处理)?

更新: 简化示例 JSON 如下所示:

{
  "set": [
    {
      "car": [
        {
          "brand": "BMW" 
        },
        {
          "brand": "Audi"
        }
      ]
    },
    {
      "car": {
        "brand": "Toyota"
      }
    } 
  ]
}

并且用下面的代码会指出doc.Set.[0].Car的类型是JsonProvider<...>.ArrayOrCar:

type example = JsonProvider<"sample.json">
let doc = example.GetSample()
doc.Set.[0].Car

在使用了库之后,我发现你可以这样做:

let car = doc.Set.[0].Car
let processObject (car:example.ArrayOrCar) = 
    match car.Array with
    | Some a -> printfn "do stuff with an array %A" a
    | None ->  match car.Record with 
               | Some c -> printfn "do stuff with an object %A" c
               | None -> printfn "fail here?"

要处理整个 Set[],您可以使用 Array.map.

之类的方法将 processObject 应用于每个元素。

如果数组中JSON值的类型与直接嵌套的JSON值的类型相同,那么JSON类型提供者实际上会统一这两种类型因此您可以使用相同的函数处理它们。

以您的最小 JSON 文档为例,以下工作:

type J = JsonProvider<"sample.json">

// The type `J.Car` is the type of the car elements in the array    
// but also of the car record directly nested in the "car" field
let printBrand (car:J.Car) =
  printfn "%s" car.Brand

// Now you can use pattern matching to check if the current element
// has an array of cars or just a single record - then you can call
// `printBrand` either on all cars or on just a single car
let doc = J.GetSample()
for set in doc.Set do
  match set.Car.Record, set.Car.Array with
  | Some c, _ -> printBrand c
  | _, Some a -> for c in a do printBrand c
  | _ -> failwith "Wrong input"