.Net Core webapi RestFul 统一接口数据返回格式

在RestFul风格盛行的年代,大部分接口都需要一套统一的数据返回格式,那么我们怎么才能保证使用统一的json数据格式返回呢,下面给大家简单介绍一下:

假如我们需要接口统一返回一下数据格式:

{
  "statusCode": 200,
  "successful": true,
  "message": null,
  "data": object
}

json对象中data是返回的实际结果对象,可以是一个对象、一个list、一个字符串、一个数字......

但是整体的json格式要以上面的为准

一般这种情况我们有两种实现方式:

1、自定义一个统一返回类

2、使用过滤器(Filter)实现

下面先介绍第一种,自定义一个接口返回类:

创建对应的接口类和实现类

  • ApiResponse.cs//实现类
  • IApiResponse.cs://几个相关的接口

IApiResponse.cs

    public interface IApiResponse
    {
        public int StatusCode { get; set; }
        public bool Successful { get; set; }
        public string? Message { get; set; }
    }

    public interface IApiResponse<T> : IApiResponse
    {
        public T? Data { get; set; }
    }

    public interface IApiErrorResponse
    {
        public Dictionary<string, object> ErrorData { get; set; }
    }

保证了所有相关对象都来自 IApiResponse 接口

ApiResponse.cs

    public class ApiResponse<T> : IApiResponse<T>
    {
        public ApiResponse()
        {
        }

        public ApiResponse(T? data)
        {
            Data = data;
        }

        public int StatusCode { get; set; } = 200;
        public bool Successful { get; set; } = true;
        public string? Message { get; set; }

        public T? Data { get; set; }

        /// <summary>
        /// 实现将 <see cref="ApiResponse"/> 隐式转换为 <see cref="ApiResponse{T}"/>
        /// </summary>
        /// <param name="apiResponse"><see cref="ApiResponse"/></param>
        public static implicit operator ApiResponse<T>(ApiResponse apiResponse)
        {
            return new ApiResponse<T>
            {
                StatusCode = apiResponse.StatusCode,
                Successful = apiResponse.Successful,
                Message = apiResponse.Message
            };
        }
    }


    public class ApiResponse : IApiResponse, IApiErrorResponse
    {
        public int StatusCode { get; set; } = 200;
        public bool Successful { get; set; } = true;
        public string? Message { get; set; }
        public object? Data { get; set; }

        /// <summary>
        /// 可序列化的错误
        /// <para>用于保存模型验证失败的错误信息</para>
        /// </summary>
        public Dictionary<string, object>? ErrorData { get; set; }

        public ApiResponse()
        {
        }

        public ApiResponse(object data)
        {
            Data = data;
        }

        public static ApiResponse NoContent(string message = "NoContent")
        {
            return new ApiResponse
            {
                StatusCode = StatusCodes.Status204NoContent,
                Successful = true,
                Message = message
            };
        }

        public static ApiResponse Ok(string message = "Ok")
        {
            return new ApiResponse
            {
                StatusCode = StatusCodes.Status200OK,
                Successful = true,
                Message = message
            };
        }

        public static ApiResponse Ok(object data, string message = "Ok")
        {
            return new ApiResponse
            {
                StatusCode = StatusCodes.Status200OK,
                Successful = true,
                Message = message,
                Data = data
            };
        }

        public static ApiResponse Unauthorized(string message = "Unauthorized")
        {
            return new ApiResponse
            {
                StatusCode = StatusCodes.Status401Unauthorized,
                Successful = false,
                Message = message
            };
        }

        public static ApiResponse NotFound(string message = "NotFound")
        {
            return new ApiResponse
            {
                StatusCode = StatusCodes.Status404NotFound,
                Successful = false,
                Message = message
            };
        }

        public static ApiResponse BadRequest(string message = "BadRequest")
        {
            return new ApiResponse
            {
                StatusCode = StatusCodes.Status400BadRequest,
                Successful = false,
                Message = message
            };
        }

        public static ApiResponse BadRequest(ModelStateDictionary modelState, string message = "ModelState is not valid.")
        {
            return new ApiResponse
            {
                StatusCode = StatusCodes.Status400BadRequest,
                Successful = false,
                Message = message,
                ErrorData = new SerializableError(modelState)
            };
        }

        public static ApiResponse Error(string message = "Error", Exception? exception = null)
        {
            object? data = null;
            if (exception != null)
            {
                data = new
                {
                    exception.Message,
                    exception.Data
                };
            }

            return new ApiResponse
            {
                StatusCode = StatusCodes.Status500InternalServerError,
                Successful = false,
                Message = message,
                Data = data
            };
        }
    }

分别实现类带有泛型的 ApiResponse<T> 类和 ApiResponse 类 

注意在泛型类中,使用运算符重载,实现了 ApiResponse 到 ApiResponse<T> 的隐式转换。

在接口实现处返回一个 ApiResponse<T> 对象:

        [HttpGet]
        public ApiResponse<UserEntity> Get(string name)
        {
            var list = new List<UserEntity>() 
            {
                new UserEntity() { Name = "张三" },
                new UserEntity(){Name = "李四"}
            };
            var user = list.Find(p => p.Name == name);
            return user == null ? ApiResponse.NotFound() : new ApiResponse<UserEntity>(user);
        }

注意看最后一句 

return user == null ? ApiResponse.NotFound() : new ApiResponse<UserEntity>(user);

ApiResponse.NotFound() 返回的是一个 ApiResponse 对象

但这接口的返回值明明是 ApiResponse<UserEntity> 类型呀,这不是类型不一致吗?

不过在 ApiResponse<T> 中,我们定义了一个运算符重载,实现了 ApiResponse 类型到 ApiResponse<T> 的隐式转换,所以就完美解决这个问题,大大减少了代码量。

来看一下最后运行效果:

下一章介绍一下如何通过自定义过滤器的方式实现统一接口返回数据格式:

.NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式-CSDN博客

最近更新

  1. TCP协议是安全的吗?

    2023-12-22 23:16:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-22 23:16:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-22 23:16:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-22 23:16:02       18 阅读

热门阅读

  1. 楼宇对讲门铃的芯片构成分析

    2023-12-22 23:16:02       38 阅读
  2. 代码随想录 279. 完全平方数

    2023-12-22 23:16:02       34 阅读
  3. 详解Qml的底层实现

    2023-12-22 23:16:02       33 阅读
  4. 人像美肤 人体美型 CVPR 2022 ABPN

    2023-12-22 23:16:02       38 阅读
  5. LeetCode 2866. 美丽塔 II

    2023-12-22 23:16:02       42 阅读
  6. RAG框架LlamaIndex核心——各种索引应用分析

    2023-12-22 23:16:02       32 阅读
  7. 【Qt之Quick模块】4. QML语法格式及命名规范

    2023-12-22 23:16:02       27 阅读
  8. 【Vue3】watch监听的五种情况

    2023-12-22 23:16:02       40 阅读
  9. Ubuntu 22.04 系统创建用户并授权sudo权限

    2023-12-22 23:16:02       44 阅读