代码之家  ›  专栏  ›  技术社区  ›  Jamie

如何在Js上迭代/映射。Json。这是一个数组吗?

  •  0
  • Jamie  · 技术社区  · 5 年前

    我试图解码一个JSON数组,它的类型是 Js.Json.t (不是 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)
                        }
                    }
                }
            }
        }
    };
    
    1 回复  |  直到 5 年前
        1
  •  2
  •   glennsl Namudon'tdie    5 年前

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

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

    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 作为速记,它返回一个 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 ,它倾向于为合成而设计,因此对于解码大型数据结构更加方便。例如,使用 @glennsll/bs-json (这里显然没有偏见):

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

    编辑:至于你得到的实际错误,你可以使用稍微不同的语法将一个curried anonymus函数变成一个uncarried函数:

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