部分反序列化 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"}

您的 StartDateEndDate 属性不在 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.