Newtonsoft Json 在反序列化为字符串时转换日期时间格式

Newtonsoft Json converts datetime format when deserializing to string

序列化器设置:

jsonSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
jsonSettings.DateFormatString = "yyyy-MM-ddTHH:mm:ss.fffffffZ";
jsonSettings.DateParseHandling = DateParseHandling.DateTimeOffset;
jsonSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;

原文json:

{
    "value": "someData",
    "startDate": "2021-01-16T00:00:00.000Z",
    "endDate": "2021-01-18T00:00:00.000Z"
}

Class 我正在反序列化为:

public class MyData
{
    [JsonConstructor]
    public MyData(string value, string startDate, string endDate)
    {
        this.Value = value;
        this.StartDate = startDate;
        this.EndDate = endDate;
    }

    public string Value { get; }
    public string StartDate { get; }
    public string EndDate { get; }
}

反序列化调用:

using (FileStream fileStream = File.OpenRead(jsonFilePath))
using (StreamReader streamReader = new StreamReader(fileStream))
using (JsonTextReader jsonReader = new JsonTextReader(streamReader))
{
    return this.JsonSerializer.Deserialize(jsonReader, typeof(MyData));
}

好吧,现在理想情况下我希望反序列化器足够聪明地说,“好吧,我认识到输入 json 中这个 'startDate' 字段的值是 DateTime 字符串,但由于我在目标类型中将其反序列化的字段是一个字符串,而不是 DateTime 或 DateTimeOffset,所以我将不理会该字符串,并使用与输入完全相同的字符串填充相应的字段。 “

但是,即使它确实决定将字符串转换为 DateTimeOffset 对象,然后在反序列化过程中将其转换回字符串,它不应该在反序列化值的设置中使用显式提供的 DateFormatString 吗?相反,这是我在 MyData 实例中看到的 StartDate 和 EndDate 字段的值:

myData.startDate == "01/16/2021 00:00:00 +00:00"
myData.endDate == "01/18/2021 00:00:00 +00:00"

现在在你提到它之前,是的,我知道我可以将 DateParseHandling 设置设置为 DateParseHandling.None,但这些序列化程序设置不仅用于这个 class,还用于许多其他现有的class是的,我不知道进行该更改是否会对代码其他部分的行为产生不利影响。

那么有什么方法可以告诉序列化程序,在显式反序列化为 DateTime 或 DateTimeOffset 对象时使用这些设置,或者在反序列化为没有定义类型的任意对象时使用这些设置,但在显式反序列化为字符串字段时保留输入日期时间字符串未更改?

或者,如果失败了,是否有一种方法可以告诉反序列化器在将日期时间字符串反序列化为字符串类型的字段时显式使用指定的 DateFormatString?

所以事实证明问题出在我们用于某些外部 classes 的自定义转换器,它首先将整个对象解析为 JObject,然后从该 JObject 进一步反序列化。我不想对此自定义转换器进行太大的更改,因为它可能会对代码库其他部分的行为产生不利影响。所以这就是我正在做的解决方法。

首先,我将 date/time 格式字符串移动到 public 常量:

public const string DefaultDateFormatString = "yyyy-MM-ddTHH:mm:ss.fffffffZ";

然后我修改了 class 上的构造函数 我在将日期字符串显式设置为我需要的格式时遇到了问题:

public class MyData
{
    public MyData(string value, string startDate, string endDate)
    {
        this.Value = value;
        this.StartDate = startDate;
        this.EndDate = endDate;
    }

    [JsonConstructor]
    public MyData(string value, DateTimeOffset startDate, DateTimeOffset endDate)
        : this(
            value, 
            startDate.ToString(JsonUtility.DefaultDateFormatString),
            endDate.ToString(JsonUtility.DefaultDateFormatString))
    {
    }

    public string Value { get; }
    public string StartDate { get; }
    public string EndDate { get; }
}