我可以为 POST 和 PUT API 请求使用自定义 JsonSerializer 来处理接口参数吗?

Posted

技术标签:

【中文标题】我可以为 POST 和 PUT API 请求使用自定义 JsonSerializer 来处理接口参数吗?【英文标题】:Can I use a custom JsonSerializer for POST and PUT API request to handle interface parameter? 【发布时间】:2021-11-05 13:01:29 【问题描述】:

我正在尝试将接口参数作为我创建的 POST 和 PUT API 的请求对象的一部分传递,但我不确定如何添加 JSON 反序列化器以便能够指定哪个具体类用于哪个服务.如何指定我想将 FooRequestData 用于一个,将 FooOtherRequestData 用于另一个?

    [ApiController]
    [Route("api/[controller]")]
    public class FooController
    
        // POST api/<APIController>
        [HttpPost]
        public FooResponse Post(FooRequest request)
        
            return FooService.Post(request);
        

        // PUT api/<APIController>
        [HttpPut]
        public FooResponse Put(FooRequest request)
        
            return FooService.Put(request);
        
    

    public class FooRequest : IRequest<Foo>
    
        public IRequestData RequestData  get; set; 
    

    public class FooRequestData : IRequestData
    
        public string Boo  get; set; 
    

    public class FooOtherRequestData : IRequestData
    
        public string Hoo  get; set; 
    

【问题讨论】:

*** 上围绕类似需求提供了各种问题/答案。它们都归结为您必须在 JSON 中包含足够的数据才能确定您应该使用哪种类型。您可以使用TypeNameHandling.Objects 使类型信息作为属性包含在 JSON 中。如果存在Boo 属性,您可以创建一个转换为一种类型的转换器,如果存在Hoo,则转换为另一种类型。您可以将 FooRequest 模型更改为具有两个可选/可为空的属性,一个用于每种可能的类型,并期望填充正确的属性。 【参考方案1】:

我认为this answer to another question 可能适合您:创建一个result filter 并将其添加到您要指定行为的控制器中。

最初我认为TextOutputFormatter 可以工作,但似乎没有办法检查请求输出格式的控制器或服务。

【讨论】:

【参考方案2】:

我了解您要执行的操作,但是它不起作用。问题不在于 API,而在于接口如何序列化/反序列化并转换为它们的继承类。

例如,如果 IRequestData 最初是 FooRequestData,但您现在决定将其转换为 FooOtherRequestData,则会引发错误,因为您无法将 IRequestData 转换为 FooOtherRequestData,如果不是以 FooOtherRequestData 开头。

相反,我会推荐以下两件事之一:

选项 1:继续使用接口

接口实际上并不像转换为父类那样删除属性。这些属性仍然存在,只是无法访问。但是当您将它作为 json 对象返回时,它仍然会显示所有属性。

虽然这是在类之间传递,但我相当肯定它也会扩展到 API 请求。

当您想将它们用作输入时,只需将接口作为要求传递即可。

选项 2:添加特定转化

在代码中工作时,您可以添加检查以查看是否可以显式转换:

if(request.RequestData.GetType().IsAssignableTo(typeof(FooRequestData))) 
   var reqData = (FooRequestData)request.RequestData;
   ...

if(request.RequestData.GetType().IsAssignableTo(typeof(FooOtherRequestData))) 
  var reqData = (FooOtherRequestData)request.RequestData;
  ...

【讨论】:

您为“特定转换”列出的选项假定request 已经被序列化为具有正确的类型。如果是这样的话,做if(request.RequestData is FooRequestData reqData) ... 会更简单。但整个问题首先是关于如何让 JSON 序列化为正确的具体类型,而不是如何将 C# 对象转换为正确的类型。

以上是关于我可以为 POST 和 PUT API 请求使用自定义 JsonSerializer 来处理接口参数吗?的主要内容,如果未能解决你的问题,请参考以下文章

javaservlet处理四种常用api请求get,put,post,delete

使用 POSTMAN 或任何其他方式批量 POST/PUT API 请求

REST API:请求正文为 JSON 或纯 POST 数据?

apipost常用操作设置

POST 和 PUT 请求中的问题,使用 axios、vuetify 数据表、vuejs

我应该使用 POST 还是 PUT 进行可以创建或更新的 API 调用