.NET Core 6中使用IHttpClientFactory反序列化HttpResponseMessage至APIResponse时的异常问题
问题排查与修复方案
嘿,我来帮你搞定这个反序列化的问题!先看你触发错误的那行核心代码:
var responseData = await JsonSerializer.DeserializeAsync<TResponse>(response);
这行代码的问题很直接:JsonSerializer.DeserializeAsync<T>的这个重载要求传入Stream类型的参数,但你传的是ReadAsStringAsync返回的字符串,所以才会抛出“无法将字符串转换为System.IO.Stream”的错误。
先修复反序列化的错误
你有两种简单的方式解决这个问题:
方案1:用字符串直接同步反序列化
既然已经把响应读成了字符串,直接用同步的JsonSerializer.Deserialize<T>就好,没必要用异步版本:
var responseData = JsonSerializer.Deserialize<TResponse>(response);
方案2:用Stream异步反序列化(更推荐)
如果想保留异步操作,跳过字符串转换的步骤,直接读取响应的Stream,这样性能也更好:
var responseStream = await httpResponseMessage.Content.ReadAsStreamAsync(); var responseData = await JsonSerializer.DeserializeAsync<TResponse>(responseStream);
解决ReadAsStreamAsync返回空对象的问题
你提到用ReadAsStreamAsync得到空对象,大概率是这几个原因:
- JSON结构和实体类不匹配:先确认API返回的JSON字段和你的
APIResponse类是否对应,比如有没有APIResponseStatus、RecordCount这些字段,大小写是否一致(默认序列化器是区分大小写的)。 - 缺少序列化配置:如果API返回的是驼峰命名的JSON,而你的类是帕斯卡命名,一定要加忽略大小写的配置:
var serializeOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, // 忽略字段名大小写匹配 // 如果需要的话,也可以配置命名策略,比如驼峰转帕斯卡 // PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; // 反序列化时传入这个配置 var responseData = await JsonSerializer.DeserializeAsync<TResponse>(responseStream, serializeOptions);
- 响应内容无效:先把响应内容打印出来看看是不是有效的JSON,比如在
ReadAsStringAsync之后加一行Console.WriteLine(response);,确认返回的内容是不是符合预期的格式。 - dynamic类型的坑:你的
APIResponse里用了dynamic? ResponseData,如果ResponseData是复杂类型,序列化器可能无法正确解析,建议换成具体的实体类,或者先用object类型试试。
修正后的完整方法示例
我把你的GetRequestAsync方法调整了一下,修复了问题,还补上了token的使用(你之前的参数没用到):
public async Task<TResponse> GetRequestAsync<TResponse>(HttpClientConfig httpClientConfig, string token) where TResponse : class { try { var apiUri = QueryHelpers.AddQueryString(httpClientConfig.ClientAPIUrl, httpClientConfig.Parameters); HttpClient httpClient = CreateClient(httpClientConfig, null); HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, apiUri); // 如果你需要携带token,记得加到请求头里 if (!string.IsNullOrEmpty(token)) { httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); } HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(httpRequestMessage); // 直接抛出非成功状态码的异常,不用手动判断 httpResponseMessage.EnsureSuccessStatusCode(); var serializeOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, }; var responseStream = await httpResponseMessage.Content.ReadAsStreamAsync(); var responseData = await JsonSerializer.DeserializeAsync<TResponse>(responseStream, serializeOptions); // 如果反序列化结果为空,抛出明确的异常 return responseData ?? throw new InvalidOperationException("反序列化后得到空对象,请检查API返回格式"); } catch (Exception ex) { // 这里可以加日志记录,方便排查问题 throw; } }
内容的提问来源于stack exchange,提问作者K.Z
相关产品推荐
相关产品推荐

