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

使用Refit传递QueryString复杂对象数组参数遇问题求助

问题分析与解决方案

你的问题核心是Refit默认未正确序列化复杂对象数组类型的Query参数,导致生成了数组自身的公共属性(如Length、LongLength)而非期望的索引式参数格式。以下是针对性的解决步骤:


1. 修正Refit接口定义

首先完善接口参数的[Query]特性,同时显式声明分页参数的Query属性:

[Get("/Hierarchies/GetHierarchy")]
[Headers("Authorization: Bearer")]
Task<List<RestHierarchy>> GetHierarchyAsync(
    [Query(CollectionFormat = CollectionFormat.Multi)] SearchParameter<RestHierarchy>[]? searchParameters = null,
    [Query] int pageNumber = 1,
    [Query] int pageSize = 50);

2. 配置Refit使用正确的Query参数格式化器

Refit默认的参数格式化器无法处理复杂对象数组的索引式序列化,需要指定基于Json的格式化器,让它遍历数组元素并展开属性:

方式一:使用Newtonsoft.Json(Json.NET)

如果项目依赖Newtonsoft.Json,创建Refit客户端时添加如下配置:

var apiClient = RestService.For<IMyApiInterface>(new HttpClient 
{ 
    BaseAddress = new Uri("https://localhost/api/") 
}, new RefitSettings
{
    QueryStringParameterFormatter = new NewtonsoftJsonQueryStringParameterFormatter(new JsonSerializerSettings
    {
        ContractResolver = new CamelCasePropertyNamesContractResolver(),
        Converters = { new StringEnumConverter() } // 确保枚举序列化为字符串
    })
});

方式二:使用System.Text.Json

如果项目使用System.Text.Json,配置如下:

var apiClient = RestService.For<IMyApiInterface>(new HttpClient 
{ 
    BaseAddress = new Uri("https://localhost/api/") 
}, new RefitSettings
{
    QueryStringParameterFormatter = new SystemTextJsonQueryStringParameterFormatter(new JsonSerializerOptions
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        Converters = { new JsonStringEnumConverter() } // 枚举转字符串
    })
});

3. 确保枚举类型正确序列化

修改SearchParameter<T>类,给LogicalOperator属性添加枚举转字符串的特性,保证生成的参数和Postman一致:

public class SearchParameter<T>
{
    public string FieldName { get; set; }
    
    // 添加此特性,让枚举序列化为字符串而非数字
    [JsonConverter(typeof(StringEnumConverter))] 
    public LogicalOperators LogicalOperator { get; set; }
    
    public string? Value1 { get; set; }
    public string? Value2 { get; set; }

    [JsonIgnore]
    private Type? FieldType
    {
        get
        {
            Type ClassType = typeof(T);
            var member = ClassType.GetMembers().FirstOrDefault(a => a.Name == FieldName);
            return member is PropertyInfo info ? info.PropertyType : ((FieldInfo)member).FieldType;
        }
    }

    public override string ToString()
    {
         // 保留原有实现
    }
}

原理说明

之前的配置仅指定了CollectionFormat.Multi,但Refit默认会将数组本身视为一个普通对象,序列化它的公共属性(如数组的Length)。通过配置Json-based的Query格式化器,Refit会遍历数组中的每个SearchParameter对象,将其属性展开为searchParameters[0].FieldName=xxx的索引式格式,与后端API的[FromQuery]绑定规则匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 04:55:23