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

时间:2017-04-02 12:17:15

标签: c# json json.net iso8601

根据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);
}

我错过了什么吗?

1 个答案:

答案 0 :(得分:1)

  

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

默认不是。

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

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

  

如果您的日期不符合ISO 8601标准,那么   DateFormatString设置可用于自定义日期格式   使用.NET 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; }
    }
}