使用Json.Net序列化时指定自定义DateTime格式

本文关键字:自定义 DateTime 格式 Json Net 序列化 使用 | 更新日期: 2023-09-27 18:30:13

我正在开发一个API,以使用ASP.NET Web API公开一些数据。

在其中一个API中,客户端希望我们以yyyy-MM-dd格式公开日期。我不想为此更改全局设置(例如GlobalConfiguration.Configuration.Formatters.JsonFormatter),因为它非常特定于此客户端。我在为多个客户开发解决方案的过程中做到了这一点。

我能想到的解决方案之一是创建一个自定义JsonConverter,然后将其放入我需要进行自定义格式化的属性中

例如

class ReturnObjectA 
{
    [JsonConverter(typeof(CustomDateTimeConverter))]
    public DateTime ReturnDate { get;set;}
}

只是想知道是否还有其他简单的方法可以做到这一点。

使用Json.Net序列化时指定自定义DateTime格式

你走在了正确的轨道上。既然您说过不能修改全局设置,那么接下来最好的办法就是根据需要应用JsonConverter属性,正如您所建议的那样。事实证明,Json.Net已经有了一个内置的IsoDateTimeConverter,可以让您指定日期格式。不幸的是,不能通过JsonConverter属性设置格式,因为该属性的唯一参数是类型。然而,有一个简单的解决方案:将IsoDateTimeConverter子类化,然后在子类的构造函数中指定日期格式。在需要的地方应用JsonConverter属性,指定您的自定义转换器,就可以开始了。以下是所需的全部代码:

class CustomDateTimeConverter : IsoDateTimeConverter
{
    public CustomDateTimeConverter()
    {
        base.DateTimeFormat = "yyyy-MM-dd";
    }
}

如果你不介意把时间也放在那里,你甚至不需要对IsoDateTimeConverter进行子类化。它的默认日期格式是yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK(如源代码中所示)。

您可以使用这种方法:

public class DateFormatConverter : IsoDateTimeConverter
{
    public DateFormatConverter(string format)
    {
        DateTimeFormat = format;
    }
}

并以这种方式使用:

class ReturnObjectA 
{
    [JsonConverter(typeof(DateFormatConverter), "yyyy-MM-dd")]
    public DateTime ReturnDate { get;set;}
}

DateTimeFormat字符串使用此处描述的.NET格式字符串语法:https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings

也可以使用IsoDateTimeConverter实例来完成,而无需更改全局格式设置:

string json = JsonConvert.SerializeObject(yourObject,
    new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });

这使用了接受params JsonConverter[]参数的JsonConvert.SerializeObject重载。

还可以使用串行器设置重载之一:

var json = JsonConvert.SerializeObject(someObject, new JsonSerializerSettings() { DateFormatString = "yyyy-MM-ddThh:mm:ssZ" });

var json = JsonConvert.SerializeObject(someObject, Formatting.Indented, new JsonSerializerSettings() { DateFormatString = "yyyy-MM-ddThh:mm:ssZ" });

采用类型的重载也可用。

我一直在使用另一个解决方案。只需创建一个字符串属性并将其用于json。此属性的返回日期格式正确。

class JSonModel {
    ...
    [JsonIgnore]
    public DateTime MyDate { get; set; }
    [JsonProperty("date")]
    public string CustomDate {
        get { return MyDate.ToString("ddMMyyyy"); }
        // set { MyDate = DateTime.Parse(value); }
        set { MyDate = DateTime.ParseExact(value, "ddMMyyyy", null); }
    }
    ...
}

这样就不必创建额外的类。此外,它还允许您创建不同的数据格式。例如,您可以使用相同的DateTime轻松地为Hour创建另一个属性。

带以下转换器

public class CustomDateTimeConverter : IsoDateTimeConverter
    {
        public CustomDateTimeConverter()
        {
            DateTimeFormat = "yyyy-MM-dd";
        }
        public CustomDateTimeConverter(string format)
        {
            DateTimeFormat = format;
        }
    }

可以将其与默认的自定义格式一起使用

class ReturnObjectA 
{
    [JsonConverter(typeof(CustomDateTimeConverter))]
    public DateTime ReturnDate { get;set;}
}

或属性的任何指定格式

class ReturnObjectB 
{
    [JsonConverter(typeof(CustomDateTimeConverter), "dd MMM yy")]
    public DateTime ReturnDate { get;set;}
}
public static JsonSerializerSettings JsonSerializer { get; set; } = new JsonSerializerSettings()
        {
            DateFormatString= "yyyy-MM-dd HH:mm:ss",
            NullValueHandling = NullValueHandling.Ignore,
            ContractResolver = new LowercaseContractResolver()
        };

你好,

当我需要设置JsonSerializerSettings 时,我会使用此属性

有些时候装饰json转换属性是不起作用的,它会通过异常表示"2010-10-01"是有效日期。为了避免这种类型,我删除了属性上的json-convert属性,并在下面的deserilizedObject方法中提到了这一点。

var addresss = JsonConvert.DeserializeObject<AddressHistory>(address, new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd" });