.net HttpClient 与自定义 JsonConverter
Posted
技术标签:
【中文标题】.net HttpClient 与自定义 JsonConverter【英文标题】:.net HttpClient with custom JsonConverter 【发布时间】:2012-12-17 13:54:13 【问题描述】:我正在使用 .NET 的 HttpClient 向 WebAPI 发出请求,该 WebAPI 返回一些 JSON 数据,需要在客户端进行一些自定义反序列化。为此,我创建了自己的JsonConverter
,但我不知道如何让ReadAsAsync<T>
方法获取转换器的存在。
我现在已经解决了我的问题,方法是使用ReadAsStringAsync
读取响应,然后将该字符串传递给JsonConvert.DeserializeObject
,但似乎应该有一个更优雅的解决方案。
这是我的代码:
public PrefsResponse GetAllPrefs(string sid)
HttpClient client = CreateHttpClient(null, sid);
var response = client.GetAsync("api/sites/" + sid).Result;
// TODO : find a way to hook custom converters to this...
// return response.Content.ReadAsAsync<PrefsResponse>().Result;
var stringResult = response.Content.ReadAsStringAsync().Result;
return JsonConvert.DeserializeObject<PrefsResponse>(stringResult, new PrefClassJsonConverter());
这是我能做的最好的,还是有更优雅的方法?
这里也是我创建 HttpClient 的地方,如果我需要连接它的话:
private HttpClient CreateHttpClient(CommandContext ctx, string sid)
var cookies = new CookieContainer();
var handler = new HttpClientHandler
CookieContainer = cookies,
UseCookies = true,
UseDefaultCredentials = false
;
// Add identity cookies:
if (ctx != null && !ctx.UserExecuting.IsAnonymous)
string userName = String.Format("0 (1)", ctx.RequestingUser.UserName, ctx.UserExecuting.Key);
cookies.Add(new Cookie(__userIdCookieName, userName));
cookies.Add(new Cookie(__sidCookieName, sid));
cookies.Add(new Cookie(__hashCookieName,
GenerateHash(userName, Prefs.Instance.UrlPrefs.SharedSecret)));
var client = new HttpClient(handler)
BaseAddress = _prefServerBaseUrl
;
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
return client;
【问题讨论】:
【参考方案1】:您可以将带有转换器列表的JsonSerializerSettings
传递给JsonMediaTypeFormatter
,ReadAsAsync<T>
将使用它:
即
var obj = await result.Content.ReadAsAsync<refsResponse>(
new[] new JsonMediaTypeFormatter
SerializerSettings = new JsonSerializerSettings
Converters = new List<JsonConverter>
//list of your converters
);
【讨论】:
我不知道 JSON.Net 有它自己的转换器概念!所以现在我们有了三样东西可以做同样的工作。派生的 HttpContent 类、派生的 MediaTypeFormatters 和派生的 JsonConverter.... 这就是我要找的。最终,我将使用我最初拥有的内容,因为我还需要在磁盘上缓存响应,以防将来请求发生故障转移。 太棒了!我需要自定义一些其他 JSON.NET 设置,而这对我来说是缺失的部分:) @filip-w 有没有办法让备用序列化程序成为默认值(即不必作为参数传入)? 在 WebAPi 中配置全局 json 转换器很容易,但在客户端应用程序中,使用HttpClient
我找不到简单的方法。问题是关于阅读响应,但是POST
ing 请求呢?我必须应用 2 个自定义格式化程序,我该怎么做?【参考方案2】:
您可能想使用HttpClient.GetStringAsync Method (String)
var response = client.GetStringAsync("api/sites/" + sid);
return JsonConvert.DeserializeObject<PrefsResponse>(response.Result, new PrefClassJsonConverter());
或者你到底想要什么更优雅?
【讨论】:
这绝对比将大量嵌套初始化器传递给Content.ReadAsAsync()
更优雅。唯一的缺点可能是将流读入一个字符串,这对于不是很大的 json 数据包来说已经足够了。在代码退出代码编辑器窗口后,我以这种方式更改了我的代码,并且没有任何格式可以帮助它。【参考方案3】:
我能够使用以下内容将自定义 JsonConverter 添加到 HttpClient 的默认格式化程序:
MediaTypeFormatterCollection formatters = new MediaTypeFormatterCollection();
formatters.JsonFormatter.SerializerSettings.Converters.Add(new MyCustomConverter());
var result = response.Content.ReadAsAsync<T>(formatters).Result;
这似乎允许您将自定义转换器添加到默认转换器。
【讨论】:
使用httpclient.PostAsJson()
时会怎样?如何传递自定义格式化程序?以上是关于.net HttpClient 与自定义 JsonConverter的主要内容,如果未能解决你的问题,请参考以下文章
Json.net 从 HTTPClient 结果反序列化 DateTime
opsworks rails.env 与自定义 json rails_env 不匹配
使用 System.Net.Http.Json 简化 HttpClient 的使用
.NET 3.1 中来自 HTTPClient 的 SendAsync 中的对象循环 Json
使用 .NET 4.0 任务模式使用 HTTPClient .ReadAsAsync 将 JSON 反序列化为数组或列表