5.31启用 JSON 响应反序列化包装器

创建于 2026 年 8 月 17 日约 3 分钟读完

在与第三方 API 进行 HTTP 远程通信时,通常会返回统一结构的 JSON 响应,例如 ApiResult<T> 类型,其中实际数据存放在 Data 属性中:

cs
public class ApiResult<T>{    public bool Success { get; set; }    public T? Data { get; set; }    // 实际返回数据}

HTTP 声明式请求通过 JsonResponseWrapperAttribute 特性来启用 JSON 响应反序列化包装器。相应的 HTTP 声明式提取器实现为 JsonResponseWrapperDeclarativeExtractor 类型,该类型负责解析 JsonResponseWrapperAttribute 特性并构建 HttpRequestBuilder 实例所需的启用 JSON 响应反序列化包装器配置。

在未启用 JSON 响应反序列化包装器功能时,每次调用都需要显式指定 ApiResult<T> 类型:

cs
public interface IHttpService : IHttpDeclarative{    [Get("https://furion.net")]    Task<ApiResult<string>> GetStringAsync();    [Get("https://furion.net/")]    Task<ApiResult<JsonModel>> GetJsonModelAsync();}

启用方式

1. 单次启用

为简化调用流程,可配置 JSON 响应反序列化包装器,使其自动提取 Data 属性内容:

cs
// 配置默认 HTTP 客户端services.AddHttpClient(string.Empty)    .ConfigureOptions(options =>    {        options.JsonResponseWrapper = new JsonResponseWrapper(typeof(ApiResult<>), nameof(ApiResult<>.Data));    });

配置完成后,通过 [JsonResponseWrapper] 启用该功能,之后只需指定目标数据类型,无需重复声明 ApiResult<T>

cs
// 在接口定义上应用,影响所有方法[JsonResponseWrapper]public interface IHttpService : IHttpDeclarative{    // 默认自动应用    [Get("https://furion.net/")]    Task<string> GetStringAsync();    // 在方法上应用    [JsonResponseWrapper]  // 可显示启用(无需)    [Get("https://furion.net/")]    Task<string> GetStringAsync();    [JsonResponseWrapper(false)]   // 禁用 JSON 响应反序列化包装器,需传入完整的响应类型    [Get("https://furion.net/")]    Task<ApiResult<JsonModel>> GetJsonModelAsync();}

框架将在运行时自动创建 ApiResult<string> 实例,并返回其 Data 属性的值。

2. 全局启用(默认对所有请求生效)

也可全局启用 JSON 响应反序列化包装器功能,只需设置 UseJsonResponseWrappertrue

cs
// 配置默认 HTTP 客户端services.AddHttpClient(string.Empty)    .ConfigureOptions(options =>    {        options.JsonResponseWrapper = new JsonResponseWrapper(typeof(ApiResult<>), nameof(ApiResult<>.Data));        options.UseJsonResponseWrapper = true;    });

全局启用后,所有请求默认使用包装功能:

cs
// [JsonResponseWrapper]   // 无需显式设置 [JsonResponseWrapper]public interface IHttpService : IHttpDeclarative{    [Get("https://furion.net/")]    Task<string> GetStringAsync();}

3. 单次禁用(覆盖全局设置)

若需对特定请求禁用该功能,可设置 [JsonResponseWrapper(false)] 特性。

自定义结果处理(ResultHandler

有时除了提取 Data,还需对响应做额外校验或转换。可通过 ResultHandler 回调实现:

cs
// 配置默认 HTTP 客户端services.AddHttpClient(string.Empty)    .ConfigureOptions(options =>    {        options.JsonResponseWrapper = new JsonResponseWrapper(typeof(ApiResult<>), nameof(ApiResult<>.Data))        {            ResultHandler = context =>            {                if (context.Instance is { } instance)                {                     // 可访问包装类型实例,获取其任意属性                    var success = context.GetPropertyValue<bool>(nameof(ApiResult<>.Success));                }                // 例如确保请求成功                context.ResponseMessage.EnsureSuccessStatusCode();                // 返回最终的目标结果(即 Data 的值)                return context.Result;            }        };    });

通过 ResultHandler,您可以在返回最终数据前执行任何自定义逻辑(如校验、转换或异常处理),使请求处理更加灵活。

context 参数的类型为 JsonResponseWrapperContext,包含以下属性和方法:

  • 属性

    • Instance:包装类型的具体实例(如 ApiResult<T>object? 类型)。
    • Result:目标结果(即 Data 的值,object? 类型)。
    • ResponseMessage:响应消息(HttpResponseMessage 类型)。
  • 方法

    • GetPropertyValue<T>(propertyName):获取包装类型的具体类型(即 Instance) 指定属性值。

JsonResponseWrapperAttribute 包含以下构造函数和属性:

  • 构造函数

    • new():作用于方法或接口,启用 JSON 响应反序列化包装器。
    • new(enabled):作用于方法或接口,设置是否启用 JSON 响应反序列化包装器。
  • 属性

    • Enabled:是否启用(bool 类型),默认值为 true(启用)。