Linda Lawton - DaImTo
Linda Lawton - DaImTo

Reputation: 117146

How to force a single property to format as a Date and not a Date time when serializing

How to force a single property to format as a Date and not a DateTime when serializing to Json? I am using System.Text.Json.Serialization NOT newtonsoft json, any solutions requiring that I use NewtonSoft jSon will not help.

I have an object which has two datetime properties in it, one is actually a date though and not a datetime.

[JsonPropertyName("startDate")]
public DateTime StartDate { get; set; }
[JsonPropertyName("startDate")]
public DateTime ActionDateTime { get; set; }

When I set it I specify that it is in fact a date.

StarDate = DateTime.Now.Date,

However when I try to serialize it to JSon

var json = JsonSerializer.Serialize(this);

I get

{"startDate":"2021-05-20T00:00:00+02:00"}

The problem being that the API endpoint I am sending this to is complaining about it being a datetime, it needs to serialize as a date. I know I could use JsonSerializerOptions but this will serialize all of the dates and I cant have that.

full code sample for your testing enjoyment

 public class Dummy
    {
        [JsonPropertyName("startDate")]
        public DateTime StartDate { get; set; }
        [JsonPropertyName("actiondatetime ")]
        public DateTime ActionDateTime { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            var hold = new Dummy();
            hold.StartDate = DateTime.Now.Date;
            hold.ActionDateTime = DateTime.Now
            var json = JsonSerializer.Serialize(hold);
            Console.WriteLine(json);
            Console.ReadLine();
        }
    }

I have searched high and low there must be a way of adding an attribute to force the single property to format as a date.

Upvotes: 1

Views: 2368

Answers (3)

Mr. Squirrel.Downy
Mr. Squirrel.Downy

Reputation: 1177

The most simple way is create a "setter property" to set serializable property.

//....else....
[JsonIgnore]
public DateTime StartDateSetter { set => StartDate = value.ToString("d"); }
[JsonPropertyName("startDate")]
public string StartDate { get; private set; }
//....else....

Because of DateTime in json will be a string, so it doesn't matter whether the source of date/time is a DateTime or string.

Upvotes: 0

MestreDosMagros
MestreDosMagros

Reputation: 1030

You can create a "ShortDate" type that have a DateTime property and create a JsonSerializerOptions for this format tha basically transform the Date field to the ToShortDateString() format on serialization.

Something like this:

public class ShortDateConverter : JsonConverter<ShortDate>
    {
        public override ShortDate ReadJson(JsonReader reader, Type objectType, ShortDate existingValue, bool hasExistingValue, JsonSerializer serializer)
        {
            return new ShortDate()
            {
                Date = DateTime.Parse((string)reader.Value)
            };
        }

        public override void WriteJson(JsonWriter writer, ShortDate value, JsonSerializer serializer)
        {
            writer.WriteValue(value.Date.ToShortDateString());
        }
    }

    public class ShortDate
    {
        [JsonProperty("date")]
        public DateTime Date { get; set; }
        public string ShotDateString => Date.ToShortDateString();
    }

And using like this:

class Program
    {
        static async Task Main(string[] args)
        {
            var ds = new ShortDate() { Date = DateTime.Now };
            var json = JsonConvert.SerializeObject(dh, new JsonSerializerSettings() { Converters = new List<JsonConverter> { new ShortDateConverter() } });

            Console.WriteLine(json);

            var obj = JsonConvert.DeserializeObject<ShortDate>(json, new JsonSerializerSettings() { Converters = new List<JsonConverter> { new ShortDateConverter() } });

            Console.WriteLine(obj);
    }
}

Of couse you will need to add validations and stuff, and register this converter on your app to not have to always specifie the formatter you want for this type. But this is the basic idea.

Upvotes: -1

Jack A.
Jack A.

Reputation: 4453

It looks like a custom converter applied using the JsonConverter attribute can do what you want. The following is sample code from the linked article:

Converter:

public class DateTimeOffsetJsonConverter : JsonConverter<DateTimeOffset>
{
    public override DateTimeOffset Read(
        ref Utf8JsonReader reader,
        Type typeToConvert,
        JsonSerializerOptions options) =>
            DateTimeOffset.ParseExact(reader.GetString(),
                "MM/dd/yyyy", CultureInfo.InvariantCulture);

    public override void Write(
        Utf8JsonWriter writer,
        DateTimeOffset dateTimeValue,
        JsonSerializerOptions options) =>
            writer.WriteStringValue(dateTimeValue.ToString(
                "MM/dd/yyyy", CultureInfo.InvariantCulture));
}

Applied using attribute:

public class WeatherForecastWithConverterAttribute
{
    [JsonConverter(typeof(DateTimeOffsetJsonConverter))]
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
}

Upvotes: 3

Related Questions