6

Having this object :

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

Returning this object as content in Web Api 2 generates this json for Birthday :

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

How can I make it to be : "2014-02-20" without the time part?

7
  • declare Birthday as string :) Commented Feb 20, 2014 at 17:09
  • Lol, unfortunatelly, not an option. :D btw, its working fine right now, but it's ugly to see that on sample code as well on repsonses. api is supposed to be consumed from outside clients and I'm sure they will be asking, what's all about the part after T on dates? :D Commented Feb 20, 2014 at 17:20
  • Bart, Don't be so sure. It is a well known format used in json's en.wikipedia.org/wiki/ISO_8601 Commented Feb 20, 2014 at 17:28
  • @L.B i know, what when the time part it's meaningless I think would be better to make it explicit by not providing it at all. Commented Feb 20, 2014 at 17:33
  • If you are open to use Json.net I can provide a custom DateTime converter. Commented Feb 20, 2014 at 17:42

5 Answers 5

11

By far the simplest method is to subclass the built in IsoDateTimeConverter class and set a different DateTimeFormat.

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

public class Foo
{
    [JsonConverter(typeof(IsoDateConverter))]
    public DateTimeOffset Date { get; set; }
}
Sign up to request clarification or add additional context in comments.

3 Comments

A nice and clean solution, simpler than the accepted one. Works well for me.
I would add Culture.DateTimeFormat.ShortDatePattern instead of hard coded "yyyy-MM-dd". Thus we can be culture dependent.
If you are using Culture.DateTimeFormat.ShortDatePattern you are using the cultures format, not the ISO format.
10
var json = JsonConvert.SerializeObject(
            new Person() { FirstName = "Joe", Birthday = DateTime.Now.AddDays(-2) },
            new ShortDateConverter()
            );

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

or Decorate your field with [JsonConverter(typeof(ShortDateConverter))]

and use like

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

3 Comments

Wow! Works like magic! :D Is there anyway to only override the WriteJson and use the default DateTime converter for the ReadJson ?
@Bart You can try this in ReadJson: serializer.Converters.Clear(); return serializer.Deserialize<DateTime>(reader);
if you get 5 more minutes do you mind explain why the clear on converters is needed? Thank you for your time, I feel like im abusing right now :/ Promise, no more questions :D
4

What about:

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

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

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

EDIT: After Habibs comment I changed it to ToShortDateString. If you want another transformation you could use ToString with the format-overload.

This depends on whether you need the whole thing bidirectional. Not sure if the empty setter is needed but I something in mind about that.

Another option could be using Json.NET serializer directly which gives you more power on what is happening including control over DateTime and others.

2 Comments

Birthday.Date.ToString() would still give time (set to 00:00:00) part as part of string, you probably need ToShortDateString()
@Habib Your right. I'll correct that in an edit. Thanks!
3

For .NET core 3.1 API:

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

And register in Startup.cs in ConfigureServices:

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

3 Comments

How would it distinguish the DateTime properties that you want serialized with this converter versus those that should be done with the default converter for those fields you want to include time?
@DaveSlinn It wouldn't, this is a solution for this particular question.
You can add it on the individual property in your model: [JsonConverter(typeof(ShortDateConverter ))] public DateTime Birthday { get; set; } Don't register ShortDateConverter in startup.cs. This will localize it to only properties you want.
0

You should use a proxy property for the serialization and mark the actual property as not serializable: Can you specify format for XmlSerialization of a datetime?

2 Comments

Question is about Json, not xml
Yes it is about Json, but the concept is the same, just use [JsonIgnore] instead of [XmlIgnore]

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.