Lar*_*335 8 .net c# json.net winforms asp.net-web-api
我有一个使用 Web API 后端的 WinForms 应用程序,我希望所有 HTTP 请求/响应都使用特定的 json SerializerSettings。在服务器端,只需在 Global.asax.cs 中执行此操作即可轻松实现:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.DateParseHandling = DateParseHandling.None;
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
Run Code Online (Sandbox Code Playgroud)
在客户端,我尝试了以下方法:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Formatting = Formatting.Indented,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
DateParseHandling = DateParseHandling.None
}.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
Run Code Online (Sandbox Code Playgroud)
当我显式使用 JsonConvert 时,这有效,例如:
var someVm = JsonConvert.DeserializeObject<SomeVm>(jsonString);
Run Code Online (Sandbox Code Playgroud)
但对于使用HttpClient.GetAsync / PostAsAsync等调用不生效,导致异常:
将值 2/24/2018 4:00:00 PM 转换为类型“System.Nullable
1[NodaTime.LocalDateTime]'. Path 'folderExpectedDate', line 16, position 45. Newtonsoft.Json.JsonSerializationException: Error converting value 2/24/2018 4:00:00 PM to type 'System.Nullable1[NodaTime.LocalDateTime]”时出错。路径“folderExpectedDate”,第 16 行,位置 45。 ---> System.ArgumentException:无法从 System.DateTime 强制转换或转换为 NodaTime.LocalDateTime。
请注意,在如上所述调用 DeserializeObject 时,导致上述异常的完全相同的 JSON 工作正常。
如何设置/修改 HttpClient 使用的默认序列化设置(我不想在每次调用中指定它 - 有数百个)?
HttpContent扩展方法在 中定义,它们使用包含,和HttpContentExtensions的私有静态。MediaTypeFormatterCollectionJsonMediaTypeFormatterXmlMediaTypeFormatternew FormUrlEncodedMediaTypeFormatter
这些扩展方法允许您传递自定义列表MediaTypeFormatter。他们使用您传递的格式化程序,或者如果您没有传递任何格式化程序,他们将使用私有静态格式化程序集合。所以作为结论:
您可以创建格式化程序的静态列表并设置它们,并在每次要调用方法时将其传递给方法。
您可以选择HttpContentExtensions使用反射来设置类的静态格式化程序集合。那么这些扩展方法将始终使用该设置。
例子
您可以创建一个公开静态私有DefaultMediaTypeFormatterCollection属性的类HttpContextException:
public class HttpClientDefaults
{
public static MediaTypeFormatterCollection MediaTypeFormatters
{
get
{
var p = typeof(HttpContentExtensions).
GetProperty("DefaultMediaTypeFormatterCollection",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Static);
return (MediaTypeFormatterCollection)p.GetValue(null, null);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后在应用程序启动时,您可以单点设置格式化程序:
var jsonFormatter = HttpClientDefaults.MediaTypeFormatters
.OfType<JsonMediaTypeFormatter>().FirstOrDefault();
// Setup jsonFormatter, for example using jsonFormatter.SerializerSettings
Run Code Online (Sandbox Code Playgroud)
该设置将用于从 json 反序列化的所有扩展方法,并且您无需更改调用这些方法的方式:
HttpClient client = new HttpClient();
var response = await client.GetAsync("http://localhost:58045/api/products/1");
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsAsync<Product>();
}
Run Code Online (Sandbox Code Playgroud)