简体   繁体   English

使用 Json.Net 序列化时指定自定义日期时间格式

[英]Specifying a custom DateTime format when serializing with Json.Net

I am developing an API to expose some data using ASP.NET Web API.我正在开发一个 API 来使用 ASP.NET Web API 公开一些数据。

In one of the API, the client wants us to expose the date in yyyy-MM-dd format.在其中一个 API 中,客户希望我们以yyyy-MM-dd格式公开日期。 I don't want to change the global settings (eg GlobalConfiguration.Configuration.Formatters.JsonFormatter ) for that since it is very specific to this client.我不想为此更改全局设置(例如GlobalConfiguration.Configuration.Formatters.JsonFormatter ),因为它非常特定于此客户端。 And I do developing that in a solution for multiple clients.我确实在为多个客户的解决方案中开发它。

One of the solution that I could think of is to create a custom JsonConverter and then put that to the property I need to do the custom formatting我能想到的解决方案之一是创建一个自定义JsonConverter ,然后将其放入我需要进行自定义格式设置的属性中

eg例如

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

Just wondering if there is some other easy way of doing that.只是想知道是否有其他简单的方法可以做到这一点。

You are on the right track.你走在正确的轨道上。 Since you said you can't modify the global settings, then the next best thing is to apply the JsonConverter attribute on an as-needed basis, as you suggested.既然你说你不能修改全局设置,那么下一个最好的办法是根据需要应用JsonConverter属性,正如你所建议的。 It turns out Json.Net already has a built-in IsoDateTimeConverter that lets you specify the date format.事实证明 Json.Net 已经有一个内置的IsoDateTimeConverter可以让你指定日期格式。 Unfortunately, you can't set the format via the JsonConverter attribute, since the attribute's sole argument is a type.不幸的是,您无法通过JsonConverter属性设置格式,因为该属性的唯一参数是类型。 However, there is a simple solution: subclass the IsoDateTimeConverter , then specify the date format in the constructor of the subclass.但是,有一个简单的解决方案:将IsoDateTimeConverter子类IsoDateTimeConverter ,然后在子类的构造函数中指定日期格式。 Apply the JsonConverter attribute where needed, specifying your custom converter, and you're ready to go.在需要的地方应用JsonConverter属性,指定您的自定义转换器,您就可以开始了。 Here is the entirety of the code needed:这是所需的全部代码:

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

If you don't mind having the time in there also, you don't even need to subclass the IsoDateTimeConverter.如果您不介意也有时间,您甚至不需要对 IsoDateTimeConverter 进行子类化。 Its default date format is yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK (as seen in the source code ).它的默认日期格式是yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK (如源代码所示)。

You could use this approach:您可以使用这种方法:

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

And use it this way:并以这种方式使用它:

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

The DateTimeFormat string uses the .NET format string syntax described here: https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings DateTimeFormat 字符串使用此处描述的 .NET 格式字符串语法: https : //docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings

It can also be done with an IsoDateTimeConverter instance, without changing global formatting settings:它也可以使用IsoDateTimeConverter实例完成,而无需更改全局格式设置:

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

This uses the JsonConvert.SerializeObject overload that takes a params JsonConverter[] argument.这使用采用params JsonConverter[]参数的JsonConvert.SerializeObject重载。

Also available using one of the serializer settings overloads:也可以使用序列化器设置重载之一:

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

Or要么

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

Overloads taking a Type are also available.也可以使用 Type 的重载。

Build helper class and apply it to your property attribute构建辅助类并将其应用于您的属性属性

Helper class:辅助类:

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

Your code use like this:您的代码使用如下:

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

There is another solution I've been using.我一直在使用另一种解决方案。 Just create a string property and use it for json.只需创建一个字符串属性并将其用于 json。 This property wil return date properly formatted.此属性将返回格式正确的日期。

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

    ...
}

This way you don't have to create extra classes.这样您就不必创建额外的类。 Also, it allows you to create diferent data formats.此外,它还允许您创建不同的数据格式。 eg, you can easily create another Property for Hour using the same DateTime.例如,您可以使用相同的日期时间轻松地为小时创建另一个属性。

With below converter带有以下转换器

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

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

Can use it with a default custom format可以使用默认的自定义格式

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

Or any specified format for a property或任何指定的属性格式

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

Hello,你好,

I'm using this property when I need set JsonSerializerSettings当我需要设置 JsonSerializerSettings 时,我正在使用此属性

Some times decorating the json convert attribute will not work ,it will through exception saying that " 2010-10-01" is valid date .有时装饰 json 转换属性不起作用,它会通过异常说“ 2010-10-01”是有效日期 To avoid this types i removed json convert attribute on the property and mentioned in the deserilizedObject method like below.为了避免这种类型,我删除了属性上的 json convert 属性,并在 deserilizedObject 方法中提到,如下所示。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM