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


137

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

在一种API中,客户希望我们以yyyy-MM-dd格式显示日期。我不想为此更改全局设置(例如GlobalConfiguration.Configuration.Formatters.JsonFormatter),因为它非常特定于此客户端。我确实在针对多个客户的解决方案中进行了开发。

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

例如

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

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


16
就其价值而言,API的用途是计算机可读性,而不是用户可读性,因此最好使用单一指定的日期格式,例如ISO 8601。如果客户端直接向用户显示API结果,或为API编写自己的日期解析代码,那么他们做错了。格式化显示日期应留在最上面的UI层。
MCattle

使用Visual Studio 2019创建Web API,此问题已通过使用System.Text.Json在ASP.NET Core 3.0中格式化DateTime进行了
Stephen

Answers:


162

您走在正确的轨道上。由于您说无法修改全局设置,因此,第二件事就是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(如源代码所示)。


1
@Koen Zomers-从我的日期格式中删除的单引号从技术上讲是正确的,尽管在这里并没有严格要求。有关自定义日期和时间格式字符串,请参阅文档中的文字字符串定界符。但是,我引用的默认格式是直接从Json.Net源代码获取的;因此,我将恢复您对此的编辑。IsonDateTimeConverter
Brian Rogers

它在带引号的地方不起作用,在没有引号的情况下也起作用,但是如果您说应该的话,我可能做错了。抱歉,编辑。
Koen Zomers

96

您可以使用这种方法:

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 : //docs.microsoft.com/zh-cn/dotnet/standard/base-types/custom-date-and-time-format-strings


5
这对我不起作用-我得到'JsonConverterAttribute' does not contain a constructor that takes 2 arguments
Tam Coton '18

1
这是最灵活的解决方案。如果出现以下错误:'JsonConverterAttribute' does not contain a constructor that takes 2 arguments,则表明您的json.net版本太旧。您需要更新到最新的json.net版本。
Florian Lavorel '18

为我工作。知道如何节省时间吗?因此,仅返回2020-02-12,例如T00:00:00
Enrico

53

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

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

这使用JsonConvert.SerializeObject带有params JsonConverter[]参数的重载。


5
如果要在许多地方序列化同一类对象,那么公认的答案比这更好
kgzdev

16

也可以使用以下序列化程序设置重载之一使用:

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" });

还提供采用类型的过载。


2
仅供参考,我想你的意思是yyyy-MM-ddTHH:mm:ssZ.. 24小时制。
Neek

9

构建帮助器类并将其应用于您的属性属性

助手类:

public class ESDateTimeConverter : IsoDateTimeConverter
{
    public ESDateTimeConverter()
    {
        base.DateTimeFormat = "yyyy-MM-ddTHH:mm:ss.fffZ";
    }
}

您的代码使用如下:

[JsonConverter(typeof(ESDateTimeConverter))]
public DateTime timestamp { get; set; }

8
您为什么还要重申其他几个人已经说过的话?
利亚姆'18

3

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

class JSonModel {
    ...

    [JsonProperty("date")]
    public string MyDate { get; set; }

    public string CustomDate {
        get { return MyDate.ToString("DDMMYY"); }
        set { MyDate = DateTime.Parse(value); }
    }

    ...
}

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


0

有时,装饰json convert属性将无法正常工作,它会通过例外说明“ 2010-10-01”为有效日期。为了避免这种类型,我删除了属性上的json convert属性,并在如下所述的deserilizedObject方法中提到了该属性。

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

0

带有下面的转换器

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

        public CustomDateTimeConverter(string format)
        {
            DateTimeFormat = format;
        }
    }

可以使用默认的自定义格式使用

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

或属性的任何指定格式

class ReturnObjectB 
{
    [JsonConverter(typeof(DateFormatConverter), "dd MMM yy")]
    public DateTime ReturnDate { get;set;}
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.