Skip to content

Commit ed07f04

Browse files
CopilotScarletKuro
andcommitted
Fix AttributeProvider documentation and move resolver tests to correct file
Co-authored-by: ScarletKuro <19953225+ScarletKuro@users.noreply.github.com>
1 parent ecfa05d commit ed07f04

4 files changed

Lines changed: 114 additions & 76 deletions

File tree

AGENT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ var options = new JsonSerializerOptions
220220
};
221221
```
222222
- Implements `IJsonTypeInfoResolver` and extends `JsonSerializerContext`
223-
- Uses `JsonPropertyInfo.AttributeProvider` to read attributes
223+
- Uses `JsonPropertyInfo.AttributeProvider` (populated by source generators in .NET 9+) to read attributes
224224
- Enables attribute syntax with source generators
225225

226226
#### 3. Factory Helper

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ var deserializedOrder = (Order?)JsonSerializer.Deserialize(json, typeof(Order),
183183

184184
### Source Generator with Attribute and Resolver (.NET 9+)
185185

186-
**.NET 9+** introduces `AttributeProvider` on `JsonPropertyInfo`, enabling attribute-based syntax with source generators via `DateTimeConverterResolver`.
186+
**.NET 9+** populates `JsonPropertyInfo.AttributeProvider` in source generators, enabling attribute-based syntax with `DateTimeConverterResolver`.
187187

188188
```csharp
189189
using Scarlet.System.Text.Json.DateTimeConverter;
@@ -319,7 +319,7 @@ This is a limitation of source generators not supporting constructor parameters
319319

320320
### .NET 9+ Resolver Requirement
321321

322-
`DateTimeConverterResolver` **only works on .NET 9+** because it relies on `JsonPropertyInfo.AttributeProvider`, which was added in .NET 9.
322+
`DateTimeConverterResolver` **only works on .NET 9+** because, while `JsonPropertyInfo.AttributeProvider` exists in .NET 7-8, it is not populated by source generators until .NET 9+. See [runtime#100095](https://github.com/dotnet/runtime/issues/100095) and [runtime#102078](https://github.com/dotnet/runtime/issues/102078) for details.
323323

324324
---
325325

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

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,115 @@ public void ReflectionBased_CompleteModel_WithAttribute_WithNullValues()
154154
Assert.Null(deserializedModel.NullableDateTimeOffsetProperty);
155155
Assert.Equal(expectedJson, json);
156156
}
157+
158+
[Fact]
159+
public void SourceGenerator_WithResolver_WithAttribute_UsingOptions()
160+
{
161+
// Arrange
162+
var sourceGenOptions = new JsonSerializerOptions
163+
{
164+
WriteIndented = true,
165+
TypeInfoResolver = new DateTimeConverterResolver(TestModelSourceGeneratorJsonSerializerContext.Default)
166+
};
167+
var originalModel = new SourceGeneratorWithResolverModel
168+
{
169+
DateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
170+
NullableDateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
171+
DateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero),
172+
NullableDateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero)
173+
};
174+
const string expectedJson = """
175+
{
176+
"DateTimeProperty": "2023-10-01T12:00:00",
177+
"NullableDateTimeProperty": "2023-10-01T12:00:00",
178+
"DateTimeOffsetProperty": "2023-10-01T12:00:00.000Z",
179+
"NullableDateTimeOffsetProperty": "2023-10-01T12:00:00.000Z"
180+
}
181+
""";
182+
183+
// Act
184+
var json = JsonSerializer.Serialize(originalModel, sourceGenOptions);
185+
var deserializedModel = JsonSerializer.Deserialize<SourceGeneratorWithResolverModel>(json, sourceGenOptions);
186+
187+
// Assert
188+
Assert.NotNull(deserializedModel);
189+
Assert.Equal(originalModel.DateTimeProperty, deserializedModel.DateTimeProperty);
190+
Assert.Equal(originalModel.NullableDateTimeProperty, deserializedModel.NullableDateTimeProperty);
191+
Assert.Equal(originalModel.DateTimeOffsetProperty, deserializedModel.DateTimeOffsetProperty);
192+
Assert.Equal(originalModel.NullableDateTimeOffsetProperty, deserializedModel.NullableDateTimeOffsetProperty);
193+
Assert.Equal(expectedJson, json);
194+
}
195+
196+
[Fact]
197+
public void SourceGenerator_WithResolver_WithAttribute_UsingContext()
198+
{
199+
// Arrange
200+
var testModelType = typeof(SourceGeneratorWithResolverModel);
201+
var context = new DateTimeConverterResolver(TestModelSourceGeneratorJsonSerializerContext.Default);
202+
var originalModel = new SourceGeneratorWithResolverModel
203+
{
204+
DateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
205+
NullableDateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
206+
DateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero),
207+
NullableDateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero)
208+
};
209+
const string expectedJson = """
210+
{
211+
"DateTimeProperty": "2023-10-01T12:00:00",
212+
"NullableDateTimeProperty": "2023-10-01T12:00:00",
213+
"DateTimeOffsetProperty": "2023-10-01T12:00:00.000Z",
214+
"NullableDateTimeOffsetProperty": "2023-10-01T12:00:00.000Z"
215+
}
216+
""";
217+
218+
// Act
219+
var json = JsonSerializer.Serialize(originalModel, testModelType, context);
220+
var deserializedModel = (SourceGeneratorWithResolverModel?)JsonSerializer.Deserialize(json, testModelType, context);
221+
222+
// Assert
223+
Assert.NotNull(deserializedModel);
224+
Assert.Equal(originalModel.DateTimeProperty, deserializedModel.DateTimeProperty);
225+
Assert.Equal(originalModel.NullableDateTimeProperty, deserializedModel.NullableDateTimeProperty);
226+
Assert.Equal(originalModel.DateTimeOffsetProperty, deserializedModel.DateTimeOffsetProperty);
227+
Assert.Equal(originalModel.NullableDateTimeOffsetProperty, deserializedModel.NullableDateTimeOffsetProperty);
228+
Assert.Equal(expectedJson, json);
229+
}
230+
231+
[Fact]
232+
public void SourceGenerator_WithResolver_WithAttribute_WithNullValues_UsingOptions()
233+
{
234+
// Arrange
235+
var sourceGenOptions = new JsonSerializerOptions
236+
{
237+
WriteIndented = true,
238+
TypeInfoResolver = new DateTimeConverterResolver(TestModelSourceGeneratorJsonSerializerContext.Default)
239+
};
240+
var originalModel = new SourceGeneratorWithResolverModel
241+
{
242+
DateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
243+
NullableDateTimeProperty = null,
244+
DateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero),
245+
NullableDateTimeOffsetProperty = null
246+
};
247+
const string expectedJson = """
248+
{
249+
"DateTimeProperty": "2023-10-01T12:00:00",
250+
"NullableDateTimeProperty": null,
251+
"DateTimeOffsetProperty": "2023-10-01T12:00:00.000Z",
252+
"NullableDateTimeOffsetProperty": null
253+
}
254+
""";
255+
256+
// Act
257+
var json = JsonSerializer.Serialize(originalModel, sourceGenOptions);
258+
var deserializedModel = JsonSerializer.Deserialize<SourceGeneratorWithResolverModel>(json, sourceGenOptions);
259+
260+
// Assert
261+
Assert.NotNull(deserializedModel);
262+
Assert.Equal(originalModel.DateTimeProperty, deserializedModel.DateTimeProperty);
263+
Assert.Null(deserializedModel.NullableDateTimeProperty);
264+
Assert.Equal(originalModel.DateTimeOffsetProperty, deserializedModel.DateTimeOffsetProperty);
265+
Assert.Null(deserializedModel.NullableDateTimeOffsetProperty);
266+
Assert.Equal(expectedJson, json);
267+
}
157268
}

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

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -114,79 +114,6 @@ public void SourceGenerator_CompleteModel_WithFormatConverter()
114114
Assert.Equal(expectedJson, json);
115115
}
116116

117-
[Fact]
118-
public void SourceGenerator_WithResolver_WithAttribute_UsingOptions()
119-
{
120-
// Arrange
121-
var sourceGenOptions = new JsonSerializerOptions
122-
{
123-
WriteIndented = true,
124-
TypeInfoResolver = new DateTimeConverterResolver(TestModelSourceGeneratorJsonSerializerContext.Default)
125-
};
126-
var originalModel = new SourceGeneratorWithResolverModel
127-
{
128-
DateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
129-
NullableDateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
130-
DateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero),
131-
NullableDateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero)
132-
};
133-
const string expectedJson = """
134-
{
135-
"DateTimeProperty": "2023-10-01T12:00:00",
136-
"NullableDateTimeProperty": "2023-10-01T12:00:00",
137-
"DateTimeOffsetProperty": "2023-10-01T12:00:00.000Z",
138-
"NullableDateTimeOffsetProperty": "2023-10-01T12:00:00.000Z"
139-
}
140-
""";
141-
142-
// Act
143-
var json = JsonSerializer.Serialize(originalModel, sourceGenOptions);
144-
var deserializedModel = JsonSerializer.Deserialize<SourceGeneratorModel>(json, sourceGenOptions);
145-
146-
// Assert
147-
Assert.NotNull(deserializedModel);
148-
Assert.Equal(originalModel.DateTimeProperty, deserializedModel.DateTimeProperty);
149-
Assert.Equal(originalModel.NullableDateTimeProperty, deserializedModel.NullableDateTimeProperty);
150-
Assert.Equal(originalModel.DateTimeOffsetProperty, deserializedModel.DateTimeOffsetProperty);
151-
Assert.Equal(originalModel.NullableDateTimeOffsetProperty, deserializedModel.NullableDateTimeOffsetProperty);
152-
Assert.Equal(expectedJson, json);
153-
}
154-
155-
[Fact]
156-
public void SourceGenerator_WithResolver_WithAttribute_UsingContext()
157-
{
158-
// Arrange
159-
var testModelType = typeof(SourceGeneratorWithResolverModel);
160-
var context = new DateTimeConverterResolver(TestModelSourceGeneratorJsonSerializerContext.Default);
161-
var originalModel = new SourceGeneratorWithResolverModel
162-
{
163-
DateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
164-
NullableDateTimeProperty = new DateTime(2023, 10, 1, 12, 0, 0, DateTimeKind.Utc),
165-
DateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero),
166-
NullableDateTimeOffsetProperty = new DateTimeOffset(2023, 10, 1, 12, 0, 0, TimeSpan.Zero)
167-
};
168-
const string expectedJson = """
169-
{
170-
"DateTimeProperty": "2023-10-01T12:00:00",
171-
"NullableDateTimeProperty": "2023-10-01T12:00:00",
172-
"DateTimeOffsetProperty": "2023-10-01T12:00:00.000Z",
173-
"NullableDateTimeOffsetProperty": "2023-10-01T12:00:00.000Z"
174-
}
175-
""";
176-
177-
// Act
178-
var json = JsonSerializer.Serialize(originalModel, testModelType, context);
179-
var deserializedModel = (SourceGeneratorWithResolverModel?)JsonSerializer.Deserialize(json, testModelType, context);
180-
181-
// Assert
182-
Assert.NotNull(deserializedModel);
183-
Assert.Equal(originalModel.DateTimeProperty, deserializedModel.DateTimeProperty);
184-
Assert.Equal(originalModel.NullableDateTimeProperty, deserializedModel.NullableDateTimeProperty);
185-
Assert.Equal(originalModel.DateTimeOffsetProperty, deserializedModel.DateTimeOffsetProperty);
186-
Assert.Equal(originalModel.NullableDateTimeOffsetProperty, deserializedModel.NullableDateTimeOffsetProperty);
187-
Assert.Equal(expectedJson, json);
188-
}
189-
190117
[Fact]
191118
public void SourceGenerator_CompleteModel_WithFormatConverter_WithNullValues()
192119
{

0 commit comments

Comments
 (0)