【问题标题】:Specifying a custom DateTime format when serializing with Json.Net使用 Json.Net 序列化时指定自定义 DateTime 格式
【发布时间】:2013-09-09 05:52:43
【问题描述】:

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

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

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

例如

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

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

【问题讨论】:

  • 对于它的价值,API 是为了计算机可读性,而不是用户可读性,因此最好坚持使用单一指定的日期格式,例如 ISO 8601。如果客户端直接向用户显示 API 结果,或者为 API 编写自己的日期解析代码,那么他们做错了。格式化显示日期应留给最顶层的 UI 层。
  • 使用 Visual Studio 2019 创建 Web API,由Formatting DateTime in ASP.NET Core 3.0 using System.Text.Json修复
  • 我避免在我的 DTO 中添加 Json.NET 细节。相反,我有你提到的 DTO 日期属性为 strings,它们使用共享的 const string 值格式化。

标签: c# datetime asp.net-web-api json.net


【解决方案1】:

你在正确的轨道上。既然您说您不能修改全局设置,那么接下来最好的做法是按照您的建议根据需要应用 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(见source code)。

【讨论】:

  • @Koen Zomers - 你从我的日期格式中删除的单引号在技术上是正确的,尽管在这里它们不是绝对必要的。请参阅documentation for Custom Date and Time Format Strings 中的文字字符串分隔符。但是,我引用的IsonDateTimeConverter 的默认格式直接取自Json.Net source code;因此,我正在恢复您对此的编辑。
  • 这里没有引号,没有引号也可以,但如果你说它应该,我可能做错了什么。抱歉编辑。
【解决方案2】:

您可以使用这种方法:

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/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings

【讨论】:

  • 这对我不起作用 - 我得到 'JsonConverterAttribute' does not contain a constructor that takes 2 arguments
  • 这是最灵活的解决方案。如果您收到以下错误:'JsonConverterAttribute' does not contain a constructor that takes 2 arguments,则表示您的 json.net 版本太旧。您需要更新到最新的 json.net 版本。
  • 为我工作。知道如何删除时间吗?所以只返回 2020-02-12 例如 T00:00:00
  • @Enrico Simple:[JsonConverter(typeof(DateFormatConverter), "yyyy-MM-dd\"T:00:00:00\"")]
  • @TamCoton 看到此错误的原因之一可能是您在文件中引用“System.Text.Json”而不是“Newtonsoft.Json”。至少这是我的问题案例。
【解决方案3】:

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

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

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

【讨论】:

  • 如果你在很多地方序列化同一个类对象,那么接受的答案比这个更好
【解决方案4】:

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

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

采用 Type 的重载也是可用的。

【讨论】:

  • 仅供参考,我认为您的意思是 yyyy-MM-ddTHH:mm:ssZ .. 24 小时制。
【解决方案5】:

我一直在使用另一种解决方案。只需创建一个字符串属性并将其用于 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 属性。

【讨论】:

    【解决方案6】:

    带有以下转换器

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

    【讨论】:

      【解决方案7】:
      public static JsonSerializerSettings JsonSerializer { get; set; } = new JsonSerializerSettings()
              {
                  DateFormatString= "yyyy-MM-dd HH:mm:ss",
                  NullValueHandling = NullValueHandling.Ignore,
                  ContractResolver = new LowercaseContractResolver()
              };
      

      你好,

      我在需要设置 JsonSerializerSettings 时使用此属性

      【讨论】:

        【解决方案8】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-19
          • 2014-06-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多