4

我从 Suave 和 F# 开始。我试图在我的 webpart 中传递一个 json 序列化对象以在我的响应中获取它。

在php中我有这个

<?php
header('Access-Control-Allow-Credentials:true');
header('Access-Control-Allow-Headers:Content-Type, Accept');
header('Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Origin:*');
?>
{
 "player1Key":"hdegftzj25",
 "gameKey":"aegfhzkfszl74852"
}

有了这个我得到了我的 json 对象,然后我尝试对 Suave 和 Newtonsoft.Json 做同样的事情

type gameCreate= {
    player1Key : string
    gameKey: string
}

let create= { player1Key = "BadBoys2"; gameKey = "zLUGgtrht4456" }

let json = Newtonsoft.Json.JsonConvert.SerializeObject(create)

//OK (acc |> Json.serialize |> Json.format )
let php =
request (fun r ->
    match r.queryParam "playerName" with
    | Choice1Of2 name ->  OK (movies |> Json.serialize(json) |> Json.format(json))
                        //|>  Response.response(Json.toJson(info))
                        //|>  OK
    | Choice2Of2 msg -> BAD_REQUEST msg)

let webPart = 
choose [
path "/" >=> (OK "Home")
path "/elm/api/create.php" >=> php
]

startWebServer defaultConfig webPart

所以我可以创建和序列化一个 json 对象,但我不知道如何在我的 web 部件中将它作为 http 响应传递,并且使用上面的代码,我在 let php 中的表达式类型上不断出现错误

4

2 回答 2

4

看起来你已经引入了太多的 Json 序列化库——你似乎混合了 Json.NET 和 Chiron(在本教程中使用),但效果不佳......

让我们退后一步。Suave 带有自己的 Json 序列化模块,因此您可以通过使用它来获得工作。下面是它的外观:

let php =
    request (fun r ->
        match r.queryParam "playerName" with
        | Choice1Of2 name ->  
            let json : string = 
                create
                // this comes from Suave.Json, gives you a byte array
                |> Json.toJson           
                // converts the byte array into a string
                |> System.Text.Encoding.UTF8.GetString
            OK json
        | Choice2Of2 msg -> BAD_REQUEST msg)

现在,如果您愿意,可以用Json.toJsonNewtonsoft Json.NET 或 Chiron 实现替换调用(但希望不是两者的混合)。只要类型对齐,你应该没问题。

特别是对于 Chiron,您缺少ToJson要序列化的类型的静态成员(这是您的教程确实提到的)。Json.NET 有一个通用的序列化函数,可以生成对应于记录模式的 json,因此开箱即用更容易一些,但如果需要,还需要更多的工作来自定义输出。

于 2017-02-03T12:28:24.153 回答
3

如果要返回带有 JSON 的 HTTP 200 响应并在 Suave 中设置 HTTP 标头,则可以使用该Writers.setHeader函数:

Writers.setHeader "Access-Control-Allow-Credentials" "true" >=>
Writers.setHeader "Access-Control-Allow-Headers:Content-Type" "Accept" >=>
Writers.setHeader "Access-Control-Allow-Methods" "GET, POST, PUT, DELETE, OPTIONS" >=>
Writers.setHeader "Access-Control-Allow-Origin" "" >=>
Successful.OK (movies |> Json.serialize |> Json.format)

整个事情是一个构造 a 的表达式,WebPart然后您可以使用 Suave 提供的功能与其他 Web 部件组合。因此,如果您想在设置标题之前进行模式匹配,您可以使用以下内容:

let php = request (fun r ->
  match r.queryParam "playerName" with
  | Choice1Of2 name ->  
      Writers.setHeader "Access-Control-Allow-Credentials" "true" >=>
      Writers.setHeader "Access-Control-Allow-Headers:Content-Type" "Accept" >=>
      Writers.setHeader 
        "Access-Control-Allow-Methods" "GET, POST, PUT, DELETE, OPTIONS" >=>
      Writers.setHeader "Access-Control-Allow-Origin" "" >=>
      Successful.OK (movies |> Json.serialize |> Json.format)
  | Choice2Of2 msg -> BAD_REQUEST msg)

当您设置 CORS 标头时,此代码段也可能会有所帮助

于 2017-02-03T12:05:29.753 回答