使用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字符串了。
想请教大家:
- 为什么
ReadFromJsonAsync<string>不能处理JSON对象格式的响应? - 有没有更优雅的方式来处理这种泛型场景,既支持自定义模型的反序列化,又能直接获取原始JSON字符串?
内容来源于stack exchange
相关产品推荐
相关产品推荐

