如何在 suave webpart 中设置 Json 响应

How to set a Json response in suave webpart

我从 Suave 和 F# 开始。 我正在尝试在我的 Web 部件中传递一个 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 响应传递,并且使用上面的代码我的表达式类型不断出错我让 php

如果您想 return 使用 JSON 的 HTTP 200 响应并在 Suave 中设置 HTTP headers,那么您可以使用 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)

整个事情是一个构造 WebPart 的表达式,然后您可以使用 Suave 提供的功能将其与其他 Web 部件组合。所以如果你想在设置 headers 之前进行模式匹配,你可以使用类似的东西:

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 时 headers、this snippet might also help

看起来你引入了一些 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.toJson 调用替换为 Newtonsoft Json.NET 或 Chiron 实现(但希望不要混合使用两者)。只要类型对齐,就应该没问题。

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