问题
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?
andDateTime
-- and generally for nullables and their underlying types.DateTime.Parse()
apparently does not support parsing multiple names time zones so if you are receivingDateTime
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