You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

API开发规范:请求与响应模型应共用还是分离?

优先选择分离的请求与响应模型

这是API设计里非常常见的问题,我的建议是尽量使用分离的请求模型和响应模型,而不是共用同一个类。原因主要有这几点:

1. 符合单一职责原则

每个模型只聚焦一件事:请求模型专门负责接收客户端传入的参数,响应模型专门定义要返回给客户端的数据结构。

拿你的例子来说,CreateUser接口里,客户端根本不需要传入CreatedOn和CreatedBy(这些是服务端生成的),如果共用UserModel,要么客户端会被要求填写这些无关字段,要么你得额外做忽略字段的逻辑;而GetUsers接口的响应,可能客户端只需要UserId、UserName、Name这类信息,没必要把内部的CreatedOn/CreatedBy暴露出去,共用模型就会被迫返回冗余甚至不必要的信息。

2. 避免数据泄露与冗余

共用模型很容易不小心把服务端内部字段(比如创建时间、创建人、数据库层面的私有字段)暴露给客户端。哪怕你用特性(比如[JsonIgnore])来忽略这些字段,随着业务扩展,模型字段越来越多,维护起来会非常麻烦,一不小心就会漏处理。

3. 更灵活的扩展空间

业务变化时,请求和响应的需求往往是独立的。比如后续你可能需要给CreateUser添加Password字段(客户端提交用),但绝对不能在响应里返回这个字段;或者给响应添加LastLoginTime字段,不需要客户端传入。如果模型分离,这些修改完全不会互相影响,代码逻辑也更清晰。

结合你的代码的改进示例

你可以拆分出三个层次的模型,让职责更清晰:

  • 内部实体模型(用于数据库操作):
public abstract class BaseEntity { 
    public DateTime CreatedOn { get; set; } 
    public int CreatedBy { get; set; } 
} 
public class UserEntity : BaseEntity { 
    public int UserId { get; set; } 
    public string UserName { get; set; } 
    public string FirstName { get; set; } 
    public string MiddleName { get; set; } 
    public string LastName { get; set; } 
    // 内部计算逻辑放在实体层
    public string FullName => $"{FirstName} {MiddleName} {LastName}".Trim();
}
  • 请求模型(客户端传入):
public class CreateUserRequest { 
    public string UserName { get; set; } 
    public string FirstName { get; set; } 
    public string MiddleName { get; set; } 
    public string LastName { get; set; } 
}
  • 响应模型(返回给客户端):
public class UserResponse { 
    public int UserId { get; set; } 
    public string UserName { get; set; } 
    public string FullName { get; set; } 
    // 如果客户端需要创建信息,再按需添加,不需要就不写
    // public DateTime CreatedOn { get; set; }
}

然后你的API可以这样实现:

public int CreateUser(CreateUserRequest request) {
    // 把请求模型转成内部实体,设置服务端生成的字段
    var userEntity = new UserEntity {
        UserName = request.UserName,
        FirstName = request.FirstName,
        MiddleName = request.MiddleName,
        LastName = request.LastName,
        CreatedOn = DateTime.Now,
        CreatedBy = CurrentUserId // 假设当前登录用户ID
    };
    // 保存到数据库,返回新用户ID
    return _userRepository.Save(userEntity);
}

public List<UserResponse> GetUsers() {
    var userEntities = _userRepository.GetAll();
    // 把内部实体转成响应模型,只返回需要的字段
    return userEntities.Select(u => new UserResponse {
        UserId = u.UserId,
        UserName = u.UserName,
        FullName = u.FullName
    }).ToList();
}

当然,如果是极端简单的场景(比如一个只返回单个ID的接口),共用模型可能暂时没问题,但从长期维护和代码健壮性来看,分离模型是更稳妥的实践。

内容的提问来源于stack exchange,提问作者S D

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 08:53:13