This package allows you to specify a custom date format for DateTime
, DateTimeOffset
, and their nullable counterparts when serializing and deserializing JSON using System.Text.Json
.
To install the Scarlet.System.Text.Json.DateTimeConverter package, run the following command in your terminal:
dotnet add package Scarlet.System.Text.Json.DateTimeConverter
Make sure you have the appropriate .NET target framework installed. This package is compatible with the following versions:
- .NET 6
- .NET 7
- .NET 8
Examples of how to serialize and deserialize models with custom date formats using JsonDateTimeConverter
attribute and JsonDateTimeFormatConverter
converter.
Note: The JsonDateTimeConverter
attribute does not support System.Text.Json
source generators. Using this attribute with JsonSerializerContext
results in SYSLIB1223: "Attributes deriving from JsonConverterAttribute
are not supported by the source generator."
In such cases, use the JsonDateTimeFormatConverter
, which also works with reflection-based serialization and deserialization. The JsonDateTimeConverter
attribute is simply less verbose and more readable than the JsonDateTimeFormatConverter
.
This will work only with reflection-based serialization and deserialization.
public class MyModel
{
[JsonDateTimeConverter("yyyy-MM-dd")]
public DateTime Date { get; set; }
[JsonDateTimeConverter("yyyy-MM-ddTHH:mm:ss.fffZ")]
public DateTimeOffset DateTimeOffset { get; set; }
}
public class Program
{
public static void Main()
{
var model = new MyModel
{
Date = DateTime.Now,
DateTimeOffset = DateTimeOffset.Now
};
// Serialize
string jsonString = JsonSerializer.Serialize(model);
Console.WriteLine($"Serialized JSON: {jsonString}");
// Deserialize
var deserializedModel = JsonSerializer.Deserialize<MyModel>(jsonString);
Console.WriteLine($"Deserialized Date: {deserializedModel.Date}");
Console.WriteLine($"Deserialized DateTimeOffset: {deserializedModel.DateTimeOffset}");
}
}
To work with System.Text.Json
source generators, use JsonDateTimeFormatConverter
instead of JsonDateTimeConverterAttribute
. This can also work with reflection-based serialization and deserialization.
public class MyModelSourceGenerator
{
[JsonConverter(typeof(JsonDateTimeFormatConverter<JsonDateTimeFormat.DateTimeFormat>))]
public DateTime Date { get; set; }
[JsonConverter(typeof(JsonDateTimeFormatConverter<JsonDateTimeFormat.DateTimeOffsetFormat>))]
public DateTimeOffset DateTimeOffset { get; set; }
}
internal class JsonDateTimeFormat
{
internal class DateTimeOffsetFormat : IJsonDateTimeFormat
{
public static string Format => "yyyy-MM-ddTHH:mm:ss.fffZ";
}
internal class DateTimeFormat : IJsonDateTimeFormat
{
public static string Format => "yyyy-MM-ddTHH:mm:ss";
}
}
[JsonSerializable(typeof(MyModelSourceGenerator))]
public sealed partial class MyModelSourceGeneratorJsonSerializerContext : JsonSerializerContext;
public class Program
{
public static void Main()
{
var modelType = typeof(MyModelSourceGenerator);
var model = new MyModelSourceGenerator
{
Date = DateTime.Now,
DateTimeOffset = DateTimeOffset.Now
};
var context = MyModelSourceGeneratorJsonSerializerContext.Default;
// Serialize
string jsonString = JsonSerializer.Serialize(model, modelType, context);
Console.WriteLine($"Serialized JSON: {jsonString}");
// Deserialize
var deserializedModel = (MyModelSourceGenerator?)JsonSerializer.Deserialize(jsonString, modelType, context);
Console.WriteLine($"Deserialized Date: {deserializedModel.Date}");
Console.WriteLine($"Deserialized DateTimeOffset: {deserializedModel.DateTimeOffset}");
}
}
Unfortunately, there is no better way with the source generator than defining a class for each date-time format. This is because the JsonConverterAttribute
is not supported by the source generator, and neither JsonConverterFactory
nor JsonConverter
allows passing the format string to the converter, as they lack constructors with parameters.
The new contract customization does not provide attribute support for the source generator as well.
- The
JsonDateTimeConverterAttribute
andJsonDateTimeFormatConverter
can be applied to properties of typeDateTime
,DateTime?
,DateTimeOffset
, andDateTimeOffset?
. - The format string provided to the attribute should follow the standard date and time format strings in .NET.