Partial deserialization Web API Core controller

不羁岁月 提交于 2021-02-11 06:10:05

问题


I have an object defined as such

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; }
 
}

A a Net Core controller takes it as a parameter. Issue is most of the time the JSON that comes only has a few of those properties (by design), which seems to cause a deserialization failure so what my controller gets is the above object with all properties set to null.

How can I tell the default net core system.text.json serialzier to accept "partial" object like that?

Adding incoming JSON

{"EndDate":"Tue, 02 Feb 2021 18:07:33 GMT","StartDate":"Tue, 26 Jan 2021 18:07:33 GMT"}

回答1:


Your StartDate and EndDate properties are not in 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.

Thus you will need to create a custom JsonConverter<DateTime?> along the lines of DateTimeConverterUsingDateTimeParse that Microsoft shows in Custom support for DateTime and DateTimeOffset such as:

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");
}

You can then add the converter to JsonSerializerOptions.Converters or apply it directly to the model like so:

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

Notes:

  • System.Text.Json seems to require distinct JsonConverter<T> converters for DateTime? and DateTime -- and generally for nullables and their underlying types.

  • DateTime.Parse() apparently does not support parsing multiple names time zones so if you are receiving DateTime strings with a mixture of different time zones, say both "GMT" and "EDT", you will need to write a more complex converter.

  • My converter assumes you want your dates and times adjusted to universal. You can modify that if it is not desired.

Demo fiddle here.



来源:https://stackoverflow.com/questions/66014283/partial-deserialization-web-api-core-controller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!