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

使用ReadFromJsonAsync<string>反序列化JSON响应失败的问题求助

ReadFromJsonAsync反序列化JSON响应失败的问题求助

大家好,我最近在封装通用HTTP请求工具的时候遇到了一个头疼的问题:当泛型参数T指定为string类型时,使用ReadFromJsonAsync<T>处理JSON响应会直接报错,但如果是反序列化成自定义的模型类,不管是用ReadFromJsonAsync<T>还是JsonConvert.DeserializeObject<T>都能正常运行。想请各位帮忙看看问题出在哪,有没有更优雅的解决方式。

场景说明

我调用的接口返回的JSON响应格式是这样的:

{ 
  "token_type": "Bearer", 
  "expires_in": 3599, 
  "ext_expires_in": 3599, 
  "access_token": "xyz" 
}

我的核心逻辑是写了一个通用的PostAsync<T>方法,判断如果T是string类型,就用ReadFromJsonAsync<T>来获取结果;否则就用JsonConvert.DeserializeObject<T>处理读取到的字符串。关键代码片段如下:

private async Task<T> PostAsync<T>(KeyValuePair<string, string>[] Content, HttpClient Client) 
{ 
    using (HttpResponseMessage responseMessage = Client.PostAsync(_requestUri, new FormUrlEncodedContent(Content)).Result) 
    { 
        responseMessage.EnsureSuccessStatusCode(); 
        if (typeof(T) == typeof(string)) 
        { 
            return await responseMessage.Content.ReadFromJsonAsync<T>(); 
        } 
        else 
        { 
            return JsonConvert.DeserializeObject<T>(await responseMessage.Content.ReadAsStringAsync()); 
        } 
    } 
}

完整的封装类代码如下:

public class IntegrationRestApi 
{ 
    public readonly IntegrationParameters Parameters; 
    private readonly IHttpClientFactory _httpFactory; 
    private static JObject _json; 
    private HttpMethod _method { get; set; } 
    private string _HttpJsonSchema { get; set; } 
    private string _requestUri { get; set; } 
    private string _host { get; set; } 

    public IntegrationRestApi(IHttpClientFactory httpClientFactory) 
    { 
        _httpFactory = httpClientFactory; 
        Parameters = new IntegrationParameters(); 
    } 

    public async Task<T> SendAsync<T>(string HttpJsonSchema) 
    { 
        if (IsValidJson(HttpJsonSchema)) 
        { 
            _HttpJsonSchema = HttpJsonSchema; 
        } 
        Parameters.ToList().ForEach(item => 
        { 
            _HttpJsonSchema = _HttpJsonSchema.Replace($"{{{item.Key}}}", item.Value); 
        }); 
        _json = JObject.Parse(_HttpJsonSchema); 
        _method = new HttpMethod(_json.Value<string>("method").ToString()); 
        _requestUri = _json.Value<string>("url").ToString(); 
        _host = _json.Value<string>("host"); 

        var jsonHeaders = "[" + _json["headers"].ToString() + "]"; 
        using(HttpClient client = _httpFactory.CreateClient()) 
        { 
            foreach(var header in JArray.Parse(jsonHeaders).Children<JObject>()) 
            { 
                foreach(JProperty parsedProperty in header.Properties()) 
                { 
                    client.DefaultRequestHeaders.Add(parsedProperty.Name, parsedProperty.Value.ToString()); 
                } 
            } 
            client.BaseAddress = new Uri(_host); 

            try 
            { 
                var jsonParameters = "[" + _json["query_parameters"].ToString() + "]"; 
                var prm = JArray.Parse(jsonParameters).Children<JObject>().FirstOrDefault(); 

                if (_method == HttpMethod.Post) 
                { 
                    var replaceContent = (from x in prm.Properties().AsEnumerable() 
                                        select new KeyValuePair<string, string>(x.Name, x.Value.ToString())).ToArray(); 
                    return await PostAsync<T>(replaceContent, client); 
                } 
                else if (_method == HttpMethod.Get) 
                { 
                    var replaceContent = (from x in prm.Properties().AsEnumerable() 
                                        select new string(string.Concat(x.Name, "=", x.Value.ToString()))).ToArray(); 
                    var queryString = string.Join("&", replaceContent); 
                    return await GetAsync<T>(queryString, client); 
                } 
                else throw new ArgumentException("Method.Is.Not.Found"); 
            } 
            catch (Exception ex) 
            { 
                throw; 
            } 
            finally 
            { 
                client.Dispose(); 
            } 
        } 
    } 

    private static bool IsValidJson(string strInput) 
    { 
        if (string.IsNullOrWhiteSpace(strInput)) 
        { 
            return false; 
        } 
        strInput = strInput.Trim(); 
        if ((strInput.StartsWith("{") && strInput.EndsWith("}")) || //For object 
            (strInput.StartsWith("[") && strInput.EndsWith("]"))) //For array 
        { 
            try 
            { 
                var obj = JToken.Parse(strInput); 
                return true; 
            } 
            catch (JsonReaderException jex) 
            { 
                return false; 
            } 
            catch (Exception ex) //some other exception 
            { 
                return false; 
            } 
        } 
        else 
        { 
            return false; 
        } 
    } 

    private async Task<T> PostAsync<T>(KeyValuePair<string, string>[] Content, HttpClient Client) 
    { 
        using(HttpResponseMessage responseMessage = Client.PostAsync(_requestUri, new FormUrlEncodedContent(Content)).Result) 
        { 
            responseMessage.EnsureSuccessStatusCode(); 
            if (typeof(T) == typeof(string)) 
            { 
                return await responseMessage.Content.ReadFromJsonAsync<T>(); 
            } 
            else 
            { 
                return JsonConvert.DeserializeObject<T>(await responseMessage.Content.ReadAsStringAsync()); 
            } 
        } 
    } 

    private async Task<T> GetAsync<T>(string QueryString, HttpClient Client) 
    { 
        _requestUri = $"{_requestUri}/{QueryString}"; 
        using(HttpResponseMessage responseMessage = Client.GetAsync(_requestUri).Result) 
        { 
            responseMessage.EnsureSuccessStatusCode(); 
            if (typeof(T).FullName == "System.String") 
            { 
                return await responseMessage.Content.ReadFromJsonAsync<T>(); 
            } 
            else 
            { 
                return JsonConvert.DeserializeObject<T>(await responseMessage.Content.ReadAsStringAsync()); 
            } 
        } 
    } 
}

我的疑问

我本来以为ReadFromJsonAsync<string>会把整个JSON响应作为字符串返回,但实际运行时会抛出反序列化错误。后来我改成直接调用await responseMessage.Content.ReadAsStringAsync()然后强制转换为T,就能正常拿到原始的JSON字符串了。

想请教大家:

  1. 为什么ReadFromJsonAsync<string>不能处理JSON对象格式的响应?
  2. 有没有更优雅的方式来处理这种泛型场景,既支持自定义模型的反序列化,又能直接获取原始JSON字符串?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 10:13:07