部分反序列化 Web API 核心控制器
Partial deserialization Web API Core controller
我有一个这样定义的对象
public class FilingSearchCriteria
{
public int? FilerId { get; set; }
public int? TypeId { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public bool? Legacy { get; set; }
public bool? NoAtttachments { get; set; }
public bool? MissingFields { get; set; }
public bool? MissingAttachments { get; set; }
public string DocketNumber { get; set; }
}
Net Core 控制器将其作为参数。问题是大多数时候出现的 JSON 只有少数这些属性(按设计),这似乎会导致反序列化失败,所以我的控制器得到的是上面的对象,所有属性都设置为 null。
如何告诉默认网络核心 system.text.json
serialzier 接受这样的“部分”对象?
添加传入JSON
{"EndDate":"Tue, 02 Feb 2021 18:07:33 GMT","StartDate":"Tue, 26 Jan 2021 18:07:33 GMT"}
您的 StartDate
和 EndDate
属性不在 ISO 8601-1:2019 format, which would look like "2021-02-02T18:07:33Z"
instead of "Tue, 02 Feb 2021 18:07:33 GMT"
. From DateTime and DateTimeOffset support in System.Text.Json 中:
The JsonSerializer, Utf8JsonReader, Utf8JsonWriter, and JsonElement types parse and write DateTime and DateTimeOffset text representations according to the extended profile of the ISO 8601-1:2019 format; for example, 2019-07-26T16:59:57-05:00.
...
With default options, input DateTime and DateTimeOffset text representations must conform to the extended ISO 8601-1:2019 profile. Attempting to deserialize representations that don't conform to the profile will cause JsonSerializer to throw a JsonException.
因此,您需要按照 Microsoft 在 Custom support for DateTime and DateTimeOffset 中显示的 DateTimeConverterUsingDateTimeParse
行创建自定义 JsonConverter<DateTime?>
,例如:
public class CustomDateTimeConverter : JsonConverter<DateTime?>
{
//const string Format = "Tue, 02 Feb 2021 18:07:33 GMT";
const string Format = "dddd, dd MMM yyyy hh:mm:ss";
// Adapted from https://docs.microsoft.com/en-us/dotnet/standard/datetime/system-text-json-support#using-datetimeoffsetparse-and-datetimeoffsettostring
public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
DateTime.Parse(reader.GetString(), CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) =>
writer.WriteStringValue(value?.ToUniversalTime().ToString(Format, CultureInfo.InvariantCulture)+" GMT");
}
然后您可以将转换器添加到 JsonSerializerOptions.Converters
或直接将其应用于模型,如下所示:
public class FilingSearchCriteria
{
public int? FilerId { get; set; }
public int? TypeId { get; set; }
[JsonConverter(typeof(CustomDateTimeConverter))]
public DateTime? StartDate { get; set; }
[JsonConverter(typeof(CustomDateTimeConverter))]
public DateTime? EndDate { get; set; }
// Remainder unchanged
备注:
System.Text.Json 似乎需要针对 DateTime?
和 DateTime
的不同 JsonConverter<T>
转换器——通常是针对可空值及其基础类型。
DateTime.Parse()
显然不支持解析 multiple names time zones 所以如果你收到 DateTime
混合了不同时区的字符串,说两个 "GMT"
和 "EDT"
,您将需要编写一个更复杂的转换器。
我的转换器假定您希望将日期和时间调整为通用的。如果不需要,您可以修改它。
演示 fiddle here.
我有一个这样定义的对象
public class FilingSearchCriteria
{
public int? FilerId { get; set; }
public int? TypeId { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public bool? Legacy { get; set; }
public bool? NoAtttachments { get; set; }
public bool? MissingFields { get; set; }
public bool? MissingAttachments { get; set; }
public string DocketNumber { get; set; }
}
Net Core 控制器将其作为参数。问题是大多数时候出现的 JSON 只有少数这些属性(按设计),这似乎会导致反序列化失败,所以我的控制器得到的是上面的对象,所有属性都设置为 null。
如何告诉默认网络核心 system.text.json
serialzier 接受这样的“部分”对象?
添加传入JSON
{"EndDate":"Tue, 02 Feb 2021 18:07:33 GMT","StartDate":"Tue, 26 Jan 2021 18:07:33 GMT"}
您的 StartDate
和 EndDate
属性不在 ISO 8601-1:2019 format, which would look like "2021-02-02T18:07:33Z"
instead of "Tue, 02 Feb 2021 18:07:33 GMT"
. From DateTime and DateTimeOffset support in System.Text.Json 中:
The JsonSerializer, Utf8JsonReader, Utf8JsonWriter, and JsonElement types parse and write DateTime and DateTimeOffset text representations according to the extended profile of the ISO 8601-1:2019 format; for example, 2019-07-26T16:59:57-05:00.
...
With default options, input DateTime and DateTimeOffset text representations must conform to the extended ISO 8601-1:2019 profile. Attempting to deserialize representations that don't conform to the profile will cause JsonSerializer to throw a JsonException.
因此,您需要按照 Microsoft 在 Custom support for DateTime and DateTimeOffset 中显示的 DateTimeConverterUsingDateTimeParse
行创建自定义 JsonConverter<DateTime?>
,例如:
public class CustomDateTimeConverter : JsonConverter<DateTime?>
{
//const string Format = "Tue, 02 Feb 2021 18:07:33 GMT";
const string Format = "dddd, dd MMM yyyy hh:mm:ss";
// Adapted from https://docs.microsoft.com/en-us/dotnet/standard/datetime/system-text-json-support#using-datetimeoffsetparse-and-datetimeoffsettostring
public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
DateTime.Parse(reader.GetString(), CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) =>
writer.WriteStringValue(value?.ToUniversalTime().ToString(Format, CultureInfo.InvariantCulture)+" GMT");
}
然后您可以将转换器添加到 JsonSerializerOptions.Converters
或直接将其应用于模型,如下所示:
public class FilingSearchCriteria
{
public int? FilerId { get; set; }
public int? TypeId { get; set; }
[JsonConverter(typeof(CustomDateTimeConverter))]
public DateTime? StartDate { get; set; }
[JsonConverter(typeof(CustomDateTimeConverter))]
public DateTime? EndDate { get; set; }
// Remainder unchanged
备注:
System.Text.Json 似乎需要针对
DateTime?
和DateTime
的不同JsonConverter<T>
转换器——通常是针对可空值及其基础类型。DateTime.Parse()
显然不支持解析 multiple names time zones 所以如果你收到DateTime
混合了不同时区的字符串,说两个"GMT"
和"EDT"
,您将需要编写一个更复杂的转换器。我的转换器假定您希望将日期和时间调整为通用的。如果不需要,您可以修改它。
演示 fiddle here.