有些人获取接口请求参数是直接使用数据库实体类来获取的,这种方式虽然写起来很方便,但是会导致swagger接口文档出现很多没用的参数,让人看着不舒服。
比如,新增用户只需要传用户名、密码、邮箱就可以了,但是实体类也包含了其他的属性,导致接口文档很难看,出现很多没用的参数,测试起来不方便。
要解决这个问题,我说一下目前见过的两种方案。
1、单独定义所谓的VO类或DTO类,将需要传递的属性定义在类里面,用接口来接收,但是保存数据库不能用VO类或DTO类,怎么办?
通常会做一次属性对拷,把同名的属性值从VO类或者DTO类拷贝到实体类里面。这种做法有个缺陷,一旦某张数据库表有几十个字段,也一个一个的去拷贝属性,写起来太麻烦了。所以,有些人会用c#里面的反射机制,分别遍历源对象和目标对象里面的属性,判断名称是否相等,再进行拷贝,封装成工具方法,或者使用第三方库。
这种算法需要写两层循环,性能并不是特别好。还有一种方法,就是把目标对象里面的属性名称保存到HashSet里面,再遍历源对象里面的属性,一一比较属性名是否包含在HashSet里面,再做属性拷贝,性能会好一点,但也就那样。
属性拷贝真的有必要吗?让我们再来看第二种方法。
2、可以定义一个类,继承实体类,作为请求参数
public class UserSaveParam:User
{
[JsonIgnore]
public long Id { get; set; }
[JsonIgnore]
public List<Role>? Roles { get; set; }
}
UserSaveParam类就是用来封装请求参数的格式的,它会把实体类里面所有的属性都继承下来,并且可以定义与实体类里面同名的属性,进行覆盖,加上JsonIgnore特性,表示相应的属性不需要做json解析,也就不会接收到相应的参数值了,其他参数值仍然可以正常接收。
然后,在接口加上这个参数
[HttpPost]
public Task<Result<object>> Save(UserSaveParam user)
{
return ExecuteCatchAsync(() => userService.SaveAsync(user));
}
其中,SaveAsync方法是这样定义的
Task<int> SaveAsync(User user);
使用User类作为参数,这也就意味着,使用UserSaveParam类的对象保存数据库,不需要再做属性对拷,也就没有了这方面的性能开销了。
生成的swagger接口文档如下
这下看起来干净多了