【问题标题】:F# WebApi return properly formatted json from a discriminated unionF# WebApi 从有区别的联合返回格式正确的 json
【发布时间】:2016-10-05 06:56:22
【问题描述】:

我想知道从 WebApi 中的歧视联合的结果中返回干净的 json 的最简单方法是什么?此用例仅用于业务逻辑,不用于 http 错误等 - 那些在管道中处理并像往常一样返回给用户(404、500 等)

例如:

type ServiceResult<'a> = { Message:string; Payload:'a }

type ServiceResponse<'a> =
    | Success of ServiceResult<'a>
    | Fail of ServiceResult<string>

返回任一:

{
  "Case": "Fail",
  "Fields": [
    {
      "Message": "Error performing business logic, your x is not in the y.",
      "Payload": "I just couldnt do it"
    }
  ]
}

...或...

{
  "Case": "Success",
  "Fields": [
    {
      "Message": "",
      "Payload": { "FirstName": "Johnny", "LastName":"Smith" }
    }
  ]
}

我希望只返回服务结果,例如:

{
  "Message": "",
  "Payload": { "FirstName": "Johnny", "LastName":"Smith" }
}

...或...

{
  "Message": "Error during operation due to spite.",
  "Payload": "I just couldnt do it"
}

我已经尝试过 IdiomaticDuConverter: https://gist.github.com/isaacabraham/ba679f285bfd15d2f53e

但它没有工作。我见过的最接近的是 Microsoft.FSharpLu.Json,但它没有 MediaTypeFormatter 可以插入管道。

我知道我可以使用 Lu 并创建自己的 MediaTypeFormatter,但我觉得必须有一种更简单的方法(比如我缺少一些 Json.Net 选项)。

你能指出我正确的方向吗?

谢谢 :-)

【问题讨论】:

    标签: f# json.net asp.net-web-api2


    【解决方案1】:

    虽然在某些极端情况下您询问的返回表示是正确的设计,但通常这不是好的 HTTP API 设计。 ASP.NET Web API返回HTTP响应,所以返回的含义

    {
      "Success": false,
      "Message": "Error during operation due to spite.",
      "Payload": "I just couldnt do it"
    }
    

    这个值是作为200 OK 响应的一部分返回的。这给客户端带来了额外的负担,因为他们现在不仅要处理 HTTP 错误(仍然可能发生),而且不能相信 200 OK 实际上意味着成功。

    如果有错误,则返回the appropriate HTTP status code

    这也解决了问题,并使您的 F# 代码易于编写。在控制器中,你基本上会做这样的事情:

    member this.Get() =
        let result = // produce the result somehow...
        match result with
        | Success x -> this.Ok x :> IHttpActionResult
        | Fail msg  -> this.BadRequest msg :> IHttpActionResult
    

    为简单起见,此示例在 Fail 情况下返回 400 Bad Request,但如果这种情况表示内部错误,则可能500 Internal Server Error 更合适。

    【讨论】:

    • 我更新了我的问题,使其更加清晰。成功/失败不是 http/server/rest 失败,它们是业务逻辑失败。但是您解决了我的问题,我只需要将结果转换为 IHttpActionResult。
    【解决方案2】:

    您可以为您的ServiceResponse 类型编写一个custom JSON.NET serializer,它会简单地跳过大小写标签并将序列化委托给嵌套的ServiceResult

    这里真正的问题是为什么你会遇到这个问题?您已经在记录中携带了成功/失败状态,DU 不提供任何附加信息。此外,通过您的设置,您可以轻松地表示看似不受欢迎的状态,如下所示:

    Success <| { Success = false; Message = "necktie"; Payload = "bacon" }
    

    为什么不直接删除它并只传递记录,完全避免序列化问题?

    【讨论】:

      猜你喜欢
      • 2015-06-30
      • 2018-11-24
      • 1970-01-01
      • 2023-02-09
      • 1970-01-01
      • 1970-01-01
      • 2014-03-01
      • 2011-10-23
      • 1970-01-01
      相关资源
      最近更新 更多