如何处理 requestbody 中布尔值的 0/1 和 false/true 值

How to handle both 0/1 and false/true values for booleans in requestbody

提问人:Sigmarod 提问时间:10/10/2023 最后编辑:Sigmarod 更新时间:10/11/2023 访问量:95

问:

我目前正在将功能从旧的 HTTP API 迁移到新的 HTTP API。 API 的多个端点需要具有可为 null 布尔值的对象作为 requestbody 中的 JSON 对象。

型号:

public class StatusRequest
{
    public bool? Status {get; set;}
}

控制器:

[HttpPost, Route("")]
public async Task<IActionResult> RequestStatus([FromBody] StatusRequest requestData )
{
    if(requestData.Status)
    {
        return Ok();
    }
    else
    { 
        return BadRequest(); 
    }
}

我现在的问题是,由于我正在从使用 0/1 整数作为布尔值的旧 API 迁移,并且我们希望用户端的必要更改尽可能少,因此 API 应该能够读取 0/1 和 false/true 请求正文中的属性。

首先,我尝试实现实现 IModelBinder 的自定义模型绑定类,该类处理 0/1 和可为 null 的值,但由于 [FromBody] 属性,该绑定被忽略。但是,我无法删除 [FromBody] 属性,因为我们的 swagger 文档将 requestmodel 显示为单个参数,而不是单个 requestbody。我也无法将请求正文的示例添加到文档中,因为 OpenApiOperation 类不再具有 RequestBody 属性。

有没有办法处理我的 nullable 和 integer 值,并且仍然有正确的文档?

C# asp.net ASP.net-Core 模型绑定 API 设计

评论


答:

1赞 IP.AF 10/10/2023 #1

您需要做的就是声明一个 .确保您的 API 用于处理 API JSON 序列化/反序列化。那么你应该创建一个自定义的 JsonConverter,它派生自并处理布尔字段。JsonConverterNewtonsoftJsonNewtonsoft.Json.JsonConverter

然后,您需要将您制作的转换器添加到newtonsoftJson中,如下所示:SerializerSettingsProgram.cs

builder.Services.AddControllers()
    .AddNewtonsoftJson(options => {
        options.SerializerSettings.Converters.Add(new BoolJsonConverter());
    });

如果你想知道如何声明一个,你可以看看我如何让 Newtonsoft 将布尔序列化为 false,而不是 False 或 “false”。BoolJsonConverter

让我们知道它是否可以帮助您解决问题。

评论

0赞 Sigmarod 10/10/2023
当我使用 .net 7 时,也应该有效,不是吗?我在整个项目中使用了System.Text.Json库,有点不愿意改变它。
0赞 IP.AF 10/11/2023
是的,System.Text.Json 还支持自定义 JSON 转换器;虽然,我找不到在MVC JSON配置中应用配置的代码示例。但它应该与 newtonsoft 配置非常相似。
0赞 Sigmarod 10/11/2023
我只是注意到这似乎没有像我想要的那样工作。我可以为 bool 类型创建一个 JsonConverter?但这只会在已经是布尔值的属性上执行。0 和 1 的整数值将被完全忽略。我也不能只实现全局整数转换器,因为我还有其他整数值,这些值可以是 0 或 1,而不表示布尔值。
0赞 IP.AF 10/11/2023 #2

另一种可能的解决方案是在同一端点上创建多个 DTO 作为 [body] 输入,如下所示

public class StatusRequest1
{
    public bool Status {get; set;}
}

public class StatusRequest2
{
    public int Status {get; set;}
}

你的控制器是这样的:

[HttpPost, Route("")]
public async Task<IActionResult> RequestStatus([FromBody] StatusRequest1 requestData )
{
    ...   
}

[HttpPost, Route("")]
public async Task<IActionResult> RequestStatus([FromBody] StatusRequest2 requestData )
{
    ...
}

之后,您可以将该值解析回 。API 客户端可以使用 int 和 bool 值调用此端点。intbool

但是,如果您唯一关心的是 and 值而不是数据类型,则可以将其声明为并将其值解析到模型内部。1/0true/falsepublic string Status {get; set;}bool