Newtonsoft.Json 序列化是否支持仅限年份的日期字段?

Does Newtonsoft.Json Serialization Support Year-Only Date Fields?

根据 ISO 8601 json 日期字段可以包含部分数据,例如"YYYY" 仅表示年或 "YYYY-MM" 仅表示年月。

但是,下面的代码使用了应该支持它的 Json.NET deserializer,抛出了格式错误:

class PartialDateContainter
{
    public DateTime MyPartialDate { get; set; }
}

[Test]
public void JustCheckJsonDates()
{
    var serializationSettings =
        new JsonSerializerSettings
        {
            DateFormatHandling = DateFormatHandling.IsoDateFormat,
            DateTimeZoneHandling = DateTimeZoneHandling.Utc,
            NullValueHandling = NullValueHandling.Ignore,
            ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
            ContractResolver = new ReadOnlyJsonContractResolver(),
            Converters = new List<JsonConverter>
            {
                new Iso8601TimeSpanConverter(),
                new IsoDateTimeConverter()
            }
        };

    var ser = JsonSerializer.Create(serializationSettings);

    var json = "{ \"MyPartialDate\": \"2005\" }";

    var shus = ser.Deserialize<PartialDateContainter>(new JsonTextReader(new StringReader(json)));

    Assert.True(true);
}

我是不是漏掉了什么?

Does Newtonsoft.Json Serialization Support Year-Only Date Fields?

默认情况下没有。

但它足够灵活,可以配置为仅支持年份日期字段。

在此处引用 Json.Net 文档 Serializing Dates in JSON

If your dates don't follow the ISO 8601 standard, then the DateFormatString setting can be used to customize the format of date strings that are read and written using .NET's custom date and time format syntax.

以下简化示例有效

[TestClass]
public class JsonNetDateSerializationTests {
    [TestMethod]
    public void JustCheckJsonDates() {
        //Arrange
        var settings =
            new JsonSerializerSettings {
                DateFormatString = "yyyy", //<-- for year only dates. all others should parse fine
            };

        var json = "{ \"YearOnly\": \"2017\", \"YearMonth\": \"2017-04\", \"YearMonthDay\": \"2017-04-02\" }";
        var expected = 2017;

        //Act
        var actual = JsonConvert.DeserializeObject<PartialDateContainter>(json, settings);

        //Assert
        Assert.IsNotNull(actual);
        Assert.AreEqual(expected, actual.YearOnly.Year);
        Assert.AreEqual(expected, actual.YearMonth.Year);
        Assert.AreEqual(expected, actual.YearMonthDay.Year);
    }

    class PartialDateContainter {
        public DateTime YearOnly { get; set; }
        public DateTime YearMonth { get; set; }
        public DateTime YearMonthDay { get; set; }
    }
}