【问题标题】:How to set a Json response in suave webpart如何在 suave webpart 中设置 Json 响应
【发布时间】:2023-03-11 09:50:02
【问题描述】:

我从 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 中的表达式类型不断出现错误

【问题讨论】:

  • 您遇到什么错误?我不知道Json.format 是什么类型,或者你从哪里得到它,但你需要将一个字符串传递给OK
  • 实际上,对于我能想到的 Json.serialize/format 的任何合理实现,您在 Choice1Of2 案例中的代码看起来非常不妥。
  • movies 是什么?这在任何地方都没有定义。
  • 抱歉,我忘了用“create”替换电影。我得到错误类型不兼容。预期(字符串 -> WebPart)-> HttpContext -> 'a 但获取字节 [] -> WebPart 类型“字符串 -> WebPart”不对应类型“字节 []”
  • 我在 Suave aspnetmonsters.com/2016/12/2016-12-31-suave987654321@上关注了一个教程

标签: php json http f# suave


【解决方案1】:

看起来你已经引入了太多的 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,因此开箱即用更容易一些,但如果需要,还需要做更多的工作来自定义输出。

【讨论】:

    【解决方案2】:

    如果您想返回一个带有 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)
    

    整个过程是一个构造 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 标头时,this snippet might also help

    【讨论】:

    • 是的,现在我正在接收我的 json 数据,但它看起来像这样 "{\"player1Key\":\"BadBoys2\",\"gameKey\":\"zLUGgtrht4456\"}"我不想要那些反斜杠。有什么想法吗?
    • Writers.setHeader "Content-Type" "application/json; charset=UTF-8" 是正确的标头。
    猜你喜欢
    • 2022-01-04
    • 1970-01-01
    • 2021-04-17
    • 2012-06-19
    • 2015-07-05
    • 1970-01-01
    • 1970-01-01
    • 2014-05-04
    • 1970-01-01
    相关资源
    最近更新 更多