【问题标题】:Serialize only Date part of DateTime in web api 2在 web api 2 中仅序列化 DateTime 的 Date 部分
【发布时间】:2014-03-21 19:14:05
【问题描述】:

拥有这个对象:

public class Person {
    public string FirstName { get; set; }
    [DataType(DataType.Date)]
    public DateTime Birthday { get; set; }
}

在 Web Api 2 中将此对象作为内容返回会生成此 json 用于生日:

"2014-02-20T17:00:32.7114097+00:00"

如果没有时间部分,我怎样才能使它成为:"2014-02-20"

【问题讨论】:

  • 声明Birthday为字符串:)
  • 大声笑,不幸的是,这不是一个选择。 :D 顺便说一句,它现在工作正常,但在示例代码和响应中看到这一点很难看。 api 应该由外部客户使用,我相信他们会问,日期 T 之后的部分是什么? :D
  • 巴特,别那么肯定。这是 json 的 en.wikipedia.org/wiki/ISO_8601 中使用的众所周知的格式
  • @L.B 我知道,当时间部分毫无意义时,我认为完全不提供它会更好。
  • 如果你愿意使用 Json.net 我可以提供一个自定义的 DateTime 转换器。

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


【解决方案1】:

到目前为止,最简单的方法是继承内置的IsoDateTimeConverter 类并设置不同的DateTimeFormat

public class IsoDateConverter : IsoDateTimeConverter
{
    public IsoDateConverter() => 
        this.DateTimeFormat = Culture.DateTimeFormat.ShortDatePattern;
}

public class Foo
{
    [JsonConverter(typeof(IsoDateConverter))]
    public DateTimeOffset Date { get; set; }
}

【讨论】:

  • 一个漂亮而干净的解决方案,比公认的更简单。很适合我。
  • 我会添加 Culture.DateTimeFormat.ShortDatePattern 而不是硬编码的“yyyy-MM-dd”。因此,我们可以依赖文化。
  • 如果您使用的是 Culture.DateTimeFormat.ShortDatePattern,您使用的是文化格式,而不是 ISO 格式。
【解决方案2】:
var json = JsonConvert.SerializeObject(
            new Person() { FirstName = "Joe", Birthday = DateTime.Now.AddDays(-2) },
            new ShortDateConverter()
            );

var p = JsonConvert.DeserializeObject<Person>(json,new ShortDateConverter());

或者用[JsonConverter(typeof(ShortDateConverter))]装饰你的领域

并使用类似

var json = JsonConvert.SerializeObject(new Person() 
                     { FirstName = "Joe", Birthday = DateTime.Now.AddDays(-2) } );

var p = JsonConvert.DeserializeObject<Person>(json);

public class ShortDateConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DateTime);
    }

    public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
    {
        return DateTime.ParseExact((string)reader.Value, "yyyy-MM-dd",CultureInfo.InvariantCulture);
    }

    public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer)
    {
        DateTime d = (DateTime)value;
        writer.WriteValue(d.ToString("yyyy-MM-dd"));
    }
}

【讨论】:

  • 哇!像魔术一样工作! :D 无论如何只覆盖 WriteJson 并为 ReadJson 使用默认的 DateTime 转换器?
  • @Bart 你可以在 ReadJson 中试试这个:serializer.Converters.Clear(); return serializer.Deserialize&lt;DateTime&gt;(reader);
  • 如果再多花 5 分钟,您介意解释一下为什么需要清除转换器吗?谢谢你的时间,我觉得我现在正在滥用:/承诺,没有更多问题:D
【解决方案3】:

怎么样:

public class Person 
{
    public string FirstName { get; set; }

    [JsonIgnore]
    public DateTime Birthday { get; set; }

    public string Birthdate 
    {
        get { return Birthday.ToShortDateString(); }   
        set {}     
    }
}

编辑:在 Habibs 发表评论后,我将其更改为 ToShortDateString。如果你想要另一个转换,你可以使用 ToString 和格式重载。

这取决于您是否需要整个双向操作。不确定是否需要空设置器,但我对此有所了解。

另一种选择是直接使用 Json.NET 序列化程序,它可以让您更了解正在发生的事情,包括控制 DateTime 等。

【讨论】:

  • Birthday.Date.ToString() 仍然会给时间 (set to 00:00:00) 部分作为字符串的一部分,您可能需要ToShortDateString()
  • @Habib 你的权利。我会在编辑中更正它。谢谢!
【解决方案4】:

对于.NET core 3.1API

public class ShortDateConverter : JsonConverter<DateTime>
{
    public override DateTime Read(
        ref Utf8JsonReader reader,
        Type typeToConvert,
        JsonSerializerOptions options)
    {
        // only supports writing
        throw new NotImplementedException();
    }

    public override void Write(
        Utf8JsonWriter writer,
        DateTime value,
        JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString("yyyy-MM-dd"));
    }
}

并在Startup.csConfigureServices注册:

 services.AddMvc()                
            .AddJsonOptions((options) =>
            {
                options.JsonSerializerOptions.Converters.Add(new ShortDateConverter());
            });
 

【讨论】:

  • 它如何区分您希望使用此转换器序列化的 DateTime 属性与那些应该使用默认转换器对您想要包含时间的字段进行序列化的属性?
  • @DaveSlinn 不会,这是针对这个特定问题的解决方案。
  • 您可以将其添加到模型中的单个属性中:[JsonConverter(typeof(ShortDateConverter ))] public DateTime Birthday { get; set; } 不要在 startup.cs 中注册 ShortDateConverter。这会将其本地化为仅您想要的属性。
【解决方案5】:

您应该使用代理属性进行序列化并将实际属性标记为不可序列化: Can you specify format for XmlSerialization of a datetime?

【讨论】:

  • 问题是关于 Json,而不是 xml
  • 是的,是关于Json的,但是概念是一样的,只是用[JsonIgnore]代替[XmlIgnore]
猜你喜欢
  • 1970-01-01
  • 2018-11-23
  • 2010-10-08
  • 2016-06-04
  • 1970-01-01
  • 2012-11-16
  • 1970-01-01
  • 2017-07-11
  • 1970-01-01
相关资源
最近更新 更多