对同一类中的多个DateTime属性使用不同的格式进行序列化

本文关键字:属性 格式 序列化 DateTime 一类 | 更新日期: 2023-09-27 18:24:48

我有一个具有两个DateTime属性的类。我需要用不同的格式序列化每个属性。我该怎么做?我试过了:

JsonConvert.SerializeObject(obj, Formatting.None,
      new IsoDateTimeConverter {DateTimeFormat = "MM.dd.yyyy"});

此解决方案不适用于我,因为它将日期格式应用于所有属性。有没有办法用不同的格式序列化每个DateTime属性?也许有某种属性?

对同一类中的多个DateTime属性使用不同的格式进行序列化

处理这种情况的一种简单方法是将IsoDateTimeConverter子类化,为您需要的每个不同的日期格式创建一个自定义日期转换器。例如:

class MonthDayYearDateConverter : IsoDateTimeConverter
{
    public MonthDayYearDateConverter()
    {
        DateTimeFormat = "MM.dd.yyyy";
    }
}
class LongDateConverter : IsoDateTimeConverter
{
    public LongDateConverter()
    {
        DateTimeFormat = "MMMM dd, yyyy";
    }
}

然后,您可以使用[JsonConverter]属性来装饰任何需要自定义格式的类中的单个DateTime属性:

class Foo
{
    [JsonConverter(typeof(MonthDayYearDateConverter))]
    public DateTime Date1 { get; set; }
    [JsonConverter(typeof(LongDateConverter))]
    public DateTime Date2 { get; set; }
    // Use default formatting
    public DateTime Date3 { get; set; }
}

演示:

Foo foo = new Foo
{
    Date1 = DateTime.Now,
    Date2 = DateTime.Now,
    Date3 = DateTime.Now
};
string json = JsonConvert.SerializeObject(foo, Formatting.Indented);
Console.WriteLine(json);

输出:

{
  "Date1": "03.03.2014",
  "Date2": "March 03, 2014",
  "Date3": "2014-03-03T10:25:49.8885852-06:00"
}

NewtonSoft.Json的结构有点难以理解,您可以使用以下自定义转换器来执行您想要的操作:

[TestMethod]
public void Conversion()
{
    var obj = new DualDate()
    {
        DateOne = new DateTime(2013, 07, 25),
        DateTwo = new DateTime(2013, 07, 25)
    };
    Assert.AreEqual("{'"DateOne'":'"07.25.2013'",'"DateTwo'":'"2013-07-25T00:00:00'"}", 
        JsonConvert.SerializeObject(obj, Formatting.None, new DualDateJsonConverter()));
}
class DualDate
{
    public DateTime DateOne { get; set; }
    public DateTime DateTwo { get; set; }
}
class DualDateJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        JObject result = new JObject();
        DualDate dd = (DualDate)value;
        result.Add("DateOne", JToken.FromObject(dd.DateOne.ToString("MM.dd.yyyy")));
        result.Add("DateTwo", JToken.FromObject(dd.DateTwo));
        result.WriteTo(writer);
    }
    // Other JsonConverterMethods
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DualDate);
    }
    public override bool CanWrite
    {
        get
        {
            return true;
        }
    }
    public override bool CanRead
    {
        get
        {
            return false;
        }
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

您可以创建一个自定义日期类,该类继承IsoDateTimeConverter并在构造函数上传递格式。在属性上,可以指定与每个属性对应的格式。参见以下代码:

public class LoginResponse
{
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }
    [JsonProperty("token_type")]
    public string TokenType { get; set; }
    [JsonProperty("expires_in")]
    public DateTime ExpiresIn { get; set; }
    [JsonProperty("userName")]
    public string Username { get; set; }
    [JsonConverter(typeof(CustomDateFormat), "EEE, dd MMM yyyy HH:mm:ss zzz")]
    [JsonProperty(".issued")]
    public DateTime Issued { get; set; }
    [JsonConverter(typeof(CustomDateFormat), "MMMM dd, yyyy")]
    [JsonProperty(".expires")]
    public DateTime Expires { get; set; }
}
public class CustomDateFormat : IsoDateTimeConverter
{
    public CustomDateFormat(string format)
    {
        DateTimeFormat = format;
    }
}

我意识到这是一个老问题,但我在搜索同一个问题时偶然发现了它。

Newtonsoft现在在JsonSerializerSettings类中有一个DateFormatString属性,您可以使用它。我来找这个问题的答案,刚刚找到了财产,我用它如下,它的工作原理如下:

    private const string _StrDateFormat = "yyyy-MM-dd HH:mm:ss";
    private static string GetJSON(object value)
    {
        return JsonConvert.SerializeObject(value, new JsonSerializerSettings
        {
            DateFormatString = _StrDateFormat
        });
    }

value将具有DateTime对象时,它将把它转换为与_StrDateFormat字符串相关的字符串。

也许这个官方链接可以更新?

谨致问候。