一个 iterate/map 怎么能超过 Js.Json.t 那是一个数组?

How can one iterate/map over a Js.Json.t that is an array?

我正在尝试解码类型为 Js.Json.t 的 JSON 数组(显然不是 array(Js.Json.t))。调用 Js.log(jsonList) 显示它是一个数组,但我不确定如何映射数组中的元素以对其进行解码。

到目前为止,我有:

let json_to_list = response => {
    switch (response |> Js.Json.decodeObject) {
        | None => {
            Js.log("Decoding JSON failed!!")
            None
        }
        | Some(jsonObject) => {
            switch (jsonObject -> Js.Dict.get("list")) {
                | None => {
                    Js.log("JSON didn't have a 'list' key/value.")
                    None
                }
                | Some(jsonList) => {
                    jsonList
                    |> Js.List.map(
                            /*  compiler is expecting an uncurried function */
                            record => {
                            switch (record->Js.Dict.get("session-id") { /* ... */ }
                        }
                    )
                }
            }
        }
    }
};

编译器需要一个未柯里化的函数,我不知道如何提供。

编辑

我想我更接近了,但我在线上收到了 This has type: array(unit) Somewhere wanted: unit(下)value |> Array.map(Js.log)

let json_to_list = response => {
    Js.log("Decoding JSON")
    switch (response |> Js.Json.decodeObject) {
        | None => {
            Js.log("Decoding JSON failed!!")
            None
        }
        | Some(jsonObject) => {
            switch (jsonObject -> Js.Dict.get("list")) {
                | None => {
                    Js.log("JSON didn't have a 'list' key/value.")
                    None
                }
                | Some(jsonArray) => switch (Js.Json.decodeArray(jsonArray)) {
                    | None => {
                        Js.log("JSON Object wasn't an array.")
                        None
                    }
                    | Some(value) => {
                        Js.log("Value length: " ++ string_of_int(value|>Js.Array.length))
                        value |> Array.map(Js.log)
                        Some(value)
                    }
                }
            }
        }
    }
};

有几种方法可以做到这一点,具体取决于您在编译时对数据的了解以及您的实际需要。

如果您确切地知道它是什么,并且您不可能收到其他任何东西,您可以直接将其转换为您想要的类型,而无需在运行时进行任何检查:

external toMyType: Js.Json.t => array(something) = "%identity"

let myData = toMyType(json)

如果直到运行时才知道数据的形状,可以使用Js.Json.classify:

let decodeArrayItem = ...

let myData : array(something) =
  switch Js.Json.classify(json) {
  | Js.Json.JSONArray(array) => Array.map(decodeArrayItem, array)
  | _ => []
  }
}

或者,如果除了数组之外你还能得到任何东西,你可以使用 Js.Json.,decodeArray 作为简写,returns 和 option 你可以处理进一步:

let decodeArrayItem = ...

let maybeData : option(array(something)) =
  Js.Json.decodeArray(json)
  |> Option.map(Array.map(decodeArrayItem))

最后,对于大多数情况,我推荐的选项是使用 one of the third-party JSON decoder libraries, which tends to be designed for composition and therefore much more convenient for decoding large data structures. For example, using @glennsll/bs-json(这里显然没有偏见):

module Decode = {
  let arrayItem = ...

  let myData =
    Json.Decode.array(arrayItem)
}

let myData =
  try Decode.myData(json) catch {
  | Js.Json.DecodeError(_) => []
  }

编辑:至于你得到的实际错误,你可以通过使用稍微不同的语法将柯里化匿名函数变成非柯里化函数:

let curried = record => ...
let uncurried = (. record) => ...