Skip to content

Commit cdad881

Browse files
committed
WIP support for sourcegen
1 parent a375816 commit cdad881

12 files changed

Lines changed: 156 additions & 26 deletions

src/Scarlet.System.Text.Json.DateTimeConverter.Tests/JsonDateTimeConverterAttributeTests.cs

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public void SerializeAndDeserialize_DateTime_ShouldMatchOriginal()
2121

2222
// Assert
2323
Assert.Equal(originalDate, deserializedDate);
24+
Assert.Equal("\"2023-10-01T12:00:00\"", json);
2425
}
2526

2627
[Fact]
@@ -39,6 +40,7 @@ public void SerializeAndDeserialize_NullableDateTime_ShouldMatchOriginal()
3940

4041
// Assert
4142
Assert.Equal(originalDate, deserializedDate);
43+
Assert.Equal("\"2023-10-01T12:00:00\"", json);
4244
}
4345

4446
[Fact]
@@ -57,6 +59,7 @@ public void SerializeAndDeserialize_DateTimeOffset_ShouldMatchOriginal()
5759

5860
// Assert
5961
Assert.Equal(originalDate, deserializedDate);
62+
Assert.Equal("\"2023-10-01T12:00:00.000Z\"", json);
6063
}
6164

6265
[Fact]
@@ -75,6 +78,7 @@ public void SerializeAndDeserialize_NullableDateTimeOffset_ShouldMatchOriginal()
7578

7679
// Assert
7780
Assert.Equal(originalDate, deserializedDate);
81+
Assert.Equal("\"2023-10-01T12:00:00.000Z\"", json);
7882
}
7983

8084
[Fact]
@@ -85,24 +89,33 @@ public void SerializeAndDeserialize_TestModel_ShouldMatchOriginal()
8589
{
8690
WriteIndented = true
8791
};
88-
var originalModel = new TestModel
92+
var originalModel = new TestModelJsonDateTimeConverter
8993
{
9094
DateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
9195
NullableDateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
9296
DateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero),
9397
NullableDateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero)
9498
};
99+
const string expectedJson = """
100+
{
101+
"DateTimeProperty": "2023-10-01T12:00:00",
102+
"NullableDateTimeProperty": "2023-10-01T12:00:00",
103+
"DateTimeOffsetProperty": "2023-10-01T12:00:00.000Z",
104+
"NullableDateTimeOffsetProperty": "2023-10-01T12:00:00.000Z"
105+
}
106+
""";
95107

96108
// Act
97109
var json = JsonSerializer.Serialize(originalModel, options);
98-
var deserializedModel = JsonSerializer.Deserialize<TestModel>(json, options);
110+
var deserializedModel = JsonSerializer.Deserialize<TestModelJsonDateTimeConverter>(json, options);
99111

100112
// Assert
101113
Assert.NotNull(deserializedModel);
102114
Assert.Equal(originalModel.DateTimeProperty, deserializedModel.DateTimeProperty);
103115
Assert.Equal(originalModel.NullableDateTimeProperty, deserializedModel.NullableDateTimeProperty);
104116
Assert.Equal(originalModel.DateTimeOffsetProperty, deserializedModel.DateTimeOffsetProperty);
105117
Assert.Equal(originalModel.NullableDateTimeOffsetProperty, deserializedModel.NullableDateTimeOffsetProperty);
118+
Assert.Equal(expectedJson, json);
106119
}
107120

108121
[Fact]
@@ -113,76 +126,102 @@ public void SerializeAndDeserialize_TestModel_WithNullValues_ShouldMatchOriginal
113126
{
114127
WriteIndented = true
115128
};
116-
var originalModel = new TestModel
129+
var originalModel = new TestModelJsonDateTimeConverter
117130
{
118131
DateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
119132
NullableDateTimeProperty = null,
120133
DateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero),
121134
NullableDateTimeOffsetProperty = null
122135
};
136+
const string expectedJson = """
137+
{
138+
"DateTimeProperty": "2023-10-01T12:00:00",
139+
"NullableDateTimeProperty": null,
140+
"DateTimeOffsetProperty": "2023-10-01T12:00:00.000Z",
141+
"NullableDateTimeOffsetProperty": null
142+
}
143+
""";
123144

124145
// Act
125146
var json = JsonSerializer.Serialize(originalModel, options);
126-
var deserializedModel = JsonSerializer.Deserialize<TestModel>(json, options);
147+
var deserializedModel = JsonSerializer.Deserialize<TestModelJsonDateTimeConverter>(json, options);
127148

128149
// Assert
129150
Assert.NotNull(deserializedModel);
130151
Assert.Equal(originalModel.DateTimeProperty, deserializedModel.DateTimeProperty);
131152
Assert.Null(deserializedModel.NullableDateTimeProperty);
132153
Assert.Equal(originalModel.DateTimeOffsetProperty, deserializedModel.DateTimeOffsetProperty);
133154
Assert.Null(deserializedModel.NullableDateTimeOffsetProperty);
155+
Assert.Equal(expectedJson, json);
134156
}
135157

136-
137158
[Fact]
138159
public void SerializeAndDeserialize_SourceGenerator_TestModel_ShouldMatchOriginal()
139160
{
140161
// Arrange
141-
var testModelType = typeof(TestModel);
142-
var context = new TestModelJsonSerializerContext();
143-
var originalModel = new TestModel
162+
var testModelType = typeof(TestModelSourceGenerator);
163+
var context = TestModelSourceGeneratorJsonSerializerContext.Default;
164+
var originalModel = new TestModelSourceGenerator
144165
{
145166
DateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
146167
NullableDateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
147168
DateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero),
148169
NullableDateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero)
149170
};
171+
const string expectedJson = """
172+
{
173+
"DateTimeProperty": "2023-10-01T12:00:00",
174+
"NullableDateTimeProperty": "2023-10-01T12:00:00",
175+
"DateTimeOffsetProperty": "2023-10-01T12:00:00.000Z",
176+
"NullableDateTimeOffsetProperty": "2023-10-01T12:00:00.000Z"
177+
}
178+
""";
150179

151180
// Act
152181
var json = JsonSerializer.Serialize(originalModel, testModelType, context);
153-
var deserializedModel = (TestModel?)JsonSerializer.Deserialize(json, testModelType, context);
182+
var deserializedModel = (TestModelSourceGenerator?)JsonSerializer.Deserialize(json, testModelType, context);
154183

155184
// Assert
156185
Assert.NotNull(deserializedModel);
157186
Assert.Equal(originalModel.DateTimeProperty, deserializedModel.DateTimeProperty);
158187
Assert.Equal(originalModel.NullableDateTimeProperty, deserializedModel.NullableDateTimeProperty);
159188
Assert.Equal(originalModel.DateTimeOffsetProperty, deserializedModel.DateTimeOffsetProperty);
160189
Assert.Equal(originalModel.NullableDateTimeOffsetProperty, deserializedModel.NullableDateTimeOffsetProperty);
190+
Assert.Equal(expectedJson, json);
161191
}
162192

163193
[Fact]
164194
public void SerializeAndDeserialize_SourceGenerator_TestModel_WithNullValues_ShouldMatchOriginal()
165195
{
166196
// Arrange
167-
var testModelType = typeof(TestModel);
168-
var context = new TestModelJsonSerializerContext();
169-
var originalModel = new TestModel
197+
var testModelType = typeof(TestModelSourceGenerator);
198+
var context = TestModelSourceGeneratorJsonSerializerContext.Default;
199+
var originalModel = new TestModelSourceGenerator
170200
{
171201
DateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
172202
NullableDateTimeProperty = null,
173203
DateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero),
174204
NullableDateTimeOffsetProperty = null
175205
};
206+
const string expectedJson = """
207+
{
208+
"DateTimeProperty": "2023-10-01T12:00:00",
209+
"NullableDateTimeProperty": null,
210+
"DateTimeOffsetProperty": "2023-10-01T12:00:00.000Z",
211+
"NullableDateTimeOffsetProperty": null
212+
}
213+
""";
176214

177215
// Act
178216
var json = JsonSerializer.Serialize(originalModel, testModelType, context);
179-
var deserializedModel = (TestModel?)JsonSerializer.Deserialize(json, testModelType, context);
217+
var deserializedModel = (TestModelSourceGenerator?)JsonSerializer.Deserialize(json, testModelType, context);
180218

181219
// Assert
182220
Assert.NotNull(deserializedModel);
183221
Assert.Equal(originalModel.DateTimeProperty, deserializedModel.DateTimeProperty);
184222
Assert.Null(deserializedModel.NullableDateTimeProperty);
185223
Assert.Equal(originalModel.DateTimeOffsetProperty, deserializedModel.DateTimeOffsetProperty);
186224
Assert.Null(deserializedModel.NullableDateTimeOffsetProperty);
225+
Assert.Equal(expectedJson, json);
187226
}
188227
}

src/Scarlet.System.Text.Json.DateTimeConverter.Tests/Model/TestModel.cs renamed to src/Scarlet.System.Text.Json.DateTimeConverter.Tests/Model/TestModelJsonDateTimeConverter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace Scarlet.System.Text.Json.DateTimeConverter.Tests.Model;
22

3-
public class TestModel
3+
public class TestModelJsonDateTimeConverter
44
{
55
[JsonDateTimeConverter("yyyy-MM-ddTHH:mm:ss")]
66
public DateTime DateTimeProperty { get; set; }
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace Scarlet.System.Text.Json.DateTimeConverter.Tests.Model;
4+
5+
public class TestModelSourceGenerator
6+
{
7+
[JsonConverter(typeof(JsonDateTimeFormatConverter<JsonDateTimeFormat.DateTimeFormat>))]
8+
public DateTime DateTimeProperty { get; set; }
9+
10+
[JsonConverter(typeof(JsonDateTimeFormatConverter<JsonDateTimeFormat.DateTimeFormat>))]
11+
public DateTime? NullableDateTimeProperty { get; set; }
12+
13+
[JsonConverter(typeof(JsonDateTimeFormatConverter<JsonDateTimeFormat.DateTimeOffsetFormat>))]
14+
public DateTimeOffset DateTimeOffsetProperty { get; set; }
15+
16+
[JsonConverter(typeof(JsonDateTimeFormatConverter<JsonDateTimeFormat.DateTimeOffsetFormat>))]
17+
public DateTimeOffset? NullableDateTimeOffsetProperty { get; set; }
18+
}
19+
20+
internal class JsonDateTimeFormat
21+
{
22+
internal class DateTimeOffsetFormat : IJsonDateTimeFormat
23+
{
24+
public static string Format => "yyyy-MM-ddTHH:mm:ss.fffZ";
25+
}
26+
internal class DateTimeFormat : IJsonDateTimeFormat
27+
{
28+
public static string Format => "yyyy-MM-ddTHH:mm:ss";
29+
}
30+
}

src/Scarlet.System.Text.Json.DateTimeConverter.Tests/Model/TestModelJsonSerializerContext.cs renamed to src/Scarlet.System.Text.Json.DateTimeConverter.Tests/Model/TestModelSourceGeneratorJsonSerializerContext.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
namespace Scarlet.System.Text.Json.DateTimeConverter.Tests.Model;
44

5-
[JsonSerializable(typeof(TestModel))]
5+
[JsonSerializable(typeof(TestModelSourceGenerator))]
66
[JsonSourceGenerationOptions(WriteIndented = true)]
7-
public sealed partial class TestModelJsonSerializerContext : JsonSerializerContext;
7+
public sealed partial class TestModelSourceGeneratorJsonSerializerContext : JsonSerializerContext;

src/Scarlet.System.Text.Json.DateTimeConverter/Converters/DateTimeConverter.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ internal sealed class DateTimeConverter : JsonConverter<DateTime>
1515
/// Initializes a new instance of the <see cref="DateTimeConverter"/> class with the specified date format.
1616
/// </summary>
1717
/// <param name="format">The date format string.</param>
18-
public DateTimeConverter(string format) => _format = format;
18+
private DateTimeConverter(string format) => _format = format;
1919

2020
/// <summary>
2121
/// Reads and converts the JSON to a <see cref="DateTime"/> object.
@@ -50,4 +50,6 @@ public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializer
5050
var date = value.ToString(_format, CultureInfo.InvariantCulture);
5151
writer.WriteStringValue(date);
5252
}
53+
54+
public static DateTimeConverter FromFormat(string format) => new(format);
5355
}

src/Scarlet.System.Text.Json.DateTimeConverter/Converters/DateTimeNullableConverter.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ internal sealed class DateTimeNullableConverter : JsonConverter<DateTime?>
1515
/// Initializes a new instance of the <see cref="DateTimeNullableConverter"/> class with the specified date format.
1616
/// </summary>
1717
/// <param name="format">The date format string.</param>
18-
public DateTimeNullableConverter(string format) => _format = format;
18+
private DateTimeNullableConverter(string format) => _format = format;
1919

2020
/// <summary>
2121
/// Reads and converts the JSON to a nullable <see cref="DateTime"/> object.
@@ -62,4 +62,6 @@ public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerialize
6262
writer.WriteNullValue();
6363
}
6464
}
65+
66+
public static DateTimeNullableConverter FromFormat(string format) => new(format);
6567
}

src/Scarlet.System.Text.Json.DateTimeConverter/Converters/DateTimeOffsetConverter.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ internal sealed class DateTimeOffsetConverter : JsonConverter<DateTimeOffset>
1515
/// Initializes a new instance of the <see cref="DateTimeOffsetConverter"/> class with the specified date format.
1616
/// </summary>
1717
/// <param name="format">The date format string.</param>
18-
public DateTimeOffsetConverter(string format) => _format = format;
18+
private DateTimeOffsetConverter(string format) => _format = format;
1919

2020
/// <summary>
2121
/// Reads and converts the JSON to a <see cref="DateTimeOffset"/> object.
@@ -50,4 +50,6 @@ public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSeri
5050
var date = value.ToString(_format, CultureInfo.InvariantCulture);
5151
writer.WriteStringValue(date);
5252
}
53+
54+
public static DateTimeOffsetConverter FromFormat(string format) => new(format);
5355
}

src/Scarlet.System.Text.Json.DateTimeConverter/Converters/DateTimeOffsetNullableConverter.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ internal sealed class DateTimeOffsetNullableConverter : JsonConverter<DateTimeOf
1515
/// Initializes a new instance of the <see cref="DateTimeOffsetNullableConverter"/> class with the specified date format.
1616
/// </summary>
1717
/// <param name="format">The date format string.</param>
18-
public DateTimeOffsetNullableConverter(string format) => _format = format;
18+
private DateTimeOffsetNullableConverter(string format) => _format = format;
1919

2020
/// <summary>
2121
/// Reads and converts the JSON to a nullable <see cref="DateTimeOffset"/> object.
@@ -62,4 +62,6 @@ public override void Write(Utf8JsonWriter writer, DateTimeOffset? value, JsonSer
6262
writer.WriteNullValue();
6363
}
6464
}
65+
66+
public static DateTimeOffsetNullableConverter FromFormat(string format) => new(format);
6567
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace Scarlet.System.Text.Json.DateTimeConverter;
2+
3+
public interface IJsonDateTimeFormat
4+
{
5+
static abstract string Format { get; }
6+
}

src/Scarlet.System.Text.Json.DateTimeConverter/JsonDateTimeConverterAttribute.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Text.Json.Serialization;
2-
using DateTime = System.DateTime;
32

43
namespace Scarlet.System.Text.Json.DateTimeConverter;
54

@@ -28,22 +27,22 @@ public override JsonConverter CreateConverter(Type typeToConvert)
2827

2928
if (typeToConvert == typeof(DateTime))
3029
{
31-
return new Converters.DateTimeConverter(Format);
30+
return Converters.DateTimeConverter.FromFormat(Format);
3231
}
3332

3433
if (typeToConvert == typeof(DateTime?))
3534
{
36-
return new Converters.DateTimeNullableConverter(Format);
35+
return Converters.DateTimeNullableConverter.FromFormat(Format);
3736
}
3837

3938
if (typeToConvert == typeof(DateTimeOffset))
4039
{
41-
return new Converters.DateTimeOffsetConverter(Format);
40+
return Converters.DateTimeOffsetConverter.FromFormat(Format);
4241
}
4342

4443
if (typeToConvert == typeof(DateTimeOffset?))
4544
{
46-
return new Converters.DateTimeOffsetNullableConverter(Format);
45+
return Converters.DateTimeOffsetNullableConverter.FromFormat(Format);
4746
}
4847

4948
throw new NotSupportedException($"{typeToConvert.FullName} is not supported by the {nameof(JsonDateTimeConverterAttribute)}.");

0 commit comments

Comments
 (0)