0

我希望能够使用模式匹配从外部 JSON 调用结果的可选属性中安全地提取值。

场景:(以openweathermap api为例)

type MyType = { cod: int option }
let printCod (x:MyType) = match x.cod with
  | Some cod -> Console.Log(cod)
  | None     -> Console.Log("EMPTY")

let success =
  fun (data, _, _) -> 
    let dat = As<MyType> data
    Console.Log(dat.cod.IsSome)  // prints false
    Console.Log(dat.cod.IsNone)  // prints false
    Console.Log(dat.cod)         // prints correct value
    printCod dat                 // prints undefined

    let dat' = {cod = Some 300}
    Console.Log(dat'.cod.IsSome) // prints true
    Console.Log(dat'.cod.IsNone) // prints false
    printCod dat'                // prints 300
    let dat'' = {cod = None}
    printCod dat''               // prints Empty

let config = 
  JQuery.AjaxConfig
    (Url = "http://api.openweathermap.org/data/2.5/weather?q=London,uk", 
     DataType = (JQuery.DataType.Jsonp :?> _), Success = [| success |])

let AjaxCall() = JQuery.JQuery.Ajax(config)

let Main =
  let _ = AjaxCall()
  ...

我希望能够通过使用 Option 来根据我的类型正确处理响应对象。如您所见,As<T>对于这种情况,转换还不够好。我找不到合适的解决方案。

有没有好的解决方法?

注意:我使用的是 Webshaper 3.0

4

2 回答 2

1

新的 OptionalField 属性已添加到最新的 WebSharper 3.0-alpha。

你现在可以写

type MyType = { [<OptionalField>] cod: int option }

并将选项值作为缺失或现有字段存储在 JS 对象上。记录创建、属性设置器和获取器以及 RPC 调用都会尊重这一点。

于 2015-02-10T18:49:39.153 回答
0

目前没有办法自动执行此操作。您需要显式转换它:

let optionField<'T> obj name =
    if JS.HasOwnProperty obj name then Some (JS.Get<'T> name obj) else None

type MyType =
  { cod: int option }
  static member FromJson(json: obj) =
    { cod = optionField json "cod" }

然后使用let dat = MyType.FromJson data.

不过,您的想法会非常有用,我将其作为提案添加到 websharper github 存储库中。

于 2015-01-22T20:44:31.163 回答