Skip to content

Commit 89efb30

Browse files
CopilotScarletKuro
andauthored
Clarify documentation: three approaches, explicit terminology, STJ source generator (#6)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: ScarletKuro <19953225+ScarletKuro@users.noreply.github.com> Co-authored-by: ScarletKuro <artem.melnikov@live.com>
1 parent 192c762 commit 89efb30

1 file changed

Lines changed: 30 additions & 31 deletions

File tree

README.md

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,11 @@ A flexible and powerful library for customizing `DateTime`, `DateTimeOffset`, `D
2525

2626
## Overview
2727

28-
This package provides four ways to specify custom date formats for `DateTime`, `DateTimeOffset`, `DateOnly`, `TimeOnly`, and their nullable counterparts when serializing and deserializing JSON using `System.Text.Json`:
28+
This package provides three ways to specify custom date formats for `DateTime`, `DateTimeOffset`, `DateOnly`, `TimeOnly`, and their nullable counterparts when serializing and deserializing JSON using `System.Text.Json`:
2929

30-
1. **`JsonDateTimeConverterAttribute`** - Simple attribute-based approach (reflection only, or .NET 9+ with resolver but produces warnings)
31-
2. **`JsonDateTimeFormatAttribute`** - Clean attribute for source generators with .NET 9+ resolver (no warnings)
32-
3. **`JsonDateTimeFormatConverter<T>`** - Type-safe converter for source generators (all .NET versions)
33-
4. **`DateTimeConverterResolver`** - Contract customization for .NET 9+ source generators
30+
1. **`JsonDateTimeConverterAttribute`** - Simple attribute-based approach for reflection-based serialization, or for System.Text.Json source generator with .NET 9+ using `DateTimeConverterResolver` (produces warnings)
31+
2. **`JsonDateTimeFormatAttribute` + `DateTimeConverterResolver`** - Clean attribute-based approach for System.Text.Json source generator with .NET 9+ (no warnings)
32+
3. **`JsonDateTimeFormatConverter<T>`** - Type-safe converter that works with both reflection-based serialization and System.Text.Json source generator (all .NET versions)
3433

3534
## Installation
3635

@@ -40,11 +39,8 @@ dotnet add package Scarlet.System.Text.Json.DateTimeConverter
4039

4140
## Prerequisites
4241

43-
- **.NET 6+** for basic functionality
44-
- **.NET 9+** for `DateTimeConverterResolver` (source generator attribute support)
45-
46-
| Target Framework | Reflection + Attribute | Source Generator + Converter | Source Generator + Attribute + Resolver |
47-
|-----------------|:---------------------:|:---------------------------:|:--------------------------------------:|
42+
| Target Framework | Reflection + Attribute | System.Text.Json Source Generator + Converter | System.Text.Json Source Generator + Attribute + Resolver |
43+
|-----------------|:---------------------:|:------------------------------------------:|:------------------------------------------------------:|
4844
| .NET 6, 7, 8 ||||
4945
| .NET 9, 10+ ||||
5046

@@ -63,7 +59,7 @@ var json = JsonSerializer.Serialize(new MyModel { Date = DateTime.Now });
6359
// Output: {"Date":"2026-01-15"}
6460
```
6561

66-
**Best for source generators** (.NET 9+, no warnings):
62+
**Best for System.Text.Json source generator** (.NET 9+, no warnings):
6763

6864
```csharp
6965
public class MyModel
@@ -142,7 +138,7 @@ var deserializedOrder = JsonSerializer.Deserialize<Order>(json);
142138

143139
### Source Generator with Format Converter (.NET 6+)
144140

145-
Use `JsonDateTimeFormatConverter<T>` for source generator compatibility across all .NET versions.
141+
Use `JsonDateTimeFormatConverter<T>` for compatibility with System.Text.Json source generator across all .NET versions. This approach also works with reflection-based serialization.
146142

147143
```csharp
148144
using Scarlet.System.Text.Json.DateTimeConverter;
@@ -218,9 +214,11 @@ var deserializedOrder = (Order?)JsonSerializer.Deserialize(json, typeof(Order),
218214
```
219215

220216
**✅ Pros:**
221-
- Works with source generators (AOT-friendly)
217+
- Works with System.Text.Json source generator (AOT-friendly)
218+
- Also works with reflection-based serialization
222219
- Compatible with all .NET versions (6+)
223220
- Type-safe format definitions
221+
- Does not require `DateTimeConverterResolver`
224222

225223
**❌ Cons:**
226224
- Requires defining a class for each date format
@@ -231,7 +229,7 @@ var deserializedOrder = (Order?)JsonSerializer.Deserialize(json, typeof(Order),
231229

232230
### Source Generator with Resolver (.NET 9+)
233231

234-
**.NET 9+** populates `JsonPropertyInfo.AttributeProvider` in source generators, enabling attribute-based syntax with `DateTimeConverterResolver`.
232+
**.NET 9+** populates `JsonPropertyInfo.AttributeProvider` in System.Text.Json source generator, enabling attribute-based syntax with `DateTimeConverterResolver`.
235233

236234
#### Option A: JsonDateTimeFormatAttribute (Recommended - No Warnings)
237235

@@ -281,18 +279,19 @@ var deserializedOrder = (Order?)JsonSerializer.Deserialize(json, typeof(Order),
281279
```
282280

283281
**✅ Pros:**
284-
- Clean attribute syntax with source generators
282+
- Clean attribute syntax with System.Text.Json source generator
285283
- AOT-friendly
286284
- **No SYSLIB1223 warnings**
287285
- Best of both worlds: readability + performance
288286

289287
**❌ Cons:**
290288
- **Requires .NET 9+**
289+
- Requires using `DateTimeConverterResolver` to wrap the context
291290
- Slightly more setup (need to wrap context with resolver)
292291

293292
#### Option B: JsonDateTimeConverterAttribute (Backward Compatible - Has Warnings)
294293

295-
You can also use `JsonDateTimeConverterAttribute` (for backward compatibility), but it will produce SYSLIB1223 warnings:
294+
You can also use `JsonDateTimeConverterAttribute` with `DateTimeConverterResolver` (for backward compatibility), but it will produce SYSLIB1223 warnings:
296295

297296
```csharp
298297
public class Order
@@ -302,7 +301,7 @@ public class Order
302301
}
303302
```
304303

305-
The resolver still works, but the source generator will emit warnings because `JsonDateTimeConverterAttribute` derives from `JsonConverterAttribute`.
304+
The resolver still works, but the System.Text.Json source generator will emit warnings because `JsonDateTimeConverterAttribute` derives from `JsonConverterAttribute`.
306305

307306
**✅ Pros:**
308307
- Works with existing code using `JsonDateTimeConverterAttribute`
@@ -325,26 +324,26 @@ A `JsonConverterAttribute`-derived attribute for specifying date formats directl
325324
public DateTime Date { get; set; }
326325
```
327326

328-
**When to use:** Reflection-based serialization. Can also be used with .NET 9+ `DateTimeConverterResolver` but produces SYSLIB1223 warnings.
327+
**When to use:** Reflection-based serialization. Can also be used with .NET 9+ System.Text.Json source generator using `DateTimeConverterResolver`, but produces SYSLIB1223 warnings.
329328

330329
---
331330

332331
### `JsonDateTimeFormatAttribute` (.NET 9+)
333332

334-
A simple `Attribute`-derived attribute for specifying date formats with source generators (no warnings).
333+
A simple `Attribute`-derived attribute for specifying date formats with System.Text.Json source generator (no warnings). Must be used with `DateTimeConverterResolver`.
335334

336335
```csharp
337336
[JsonDateTimeFormat("yyyy-MM-dd")]
338337
public DateTime Date { get; set; }
339338
```
340339

341-
**When to use:** .NET 9+ source generators with `DateTimeConverterResolver` (recommended, no warnings).
340+
**When to use:** .NET 9+ System.Text.Json source generator with `DateTimeConverterResolver` (recommended, no warnings).
342341

343342
---
344343

345344
### `JsonDateTimeFormatConverter<T>`
346345

347-
A `JsonConverterFactory` that uses `IJsonDateTimeFormat` implementations to define formats.
346+
A `JsonConverterFactory` that uses `IJsonDateTimeFormat` implementations to define formats. Works with both reflection-based serialization and System.Text.Json source generator.
348347

349348
```csharp
350349
public class MyFormat : IJsonDateTimeFormat
@@ -356,20 +355,20 @@ public class MyFormat : IJsonDateTimeFormat
356355
public DateTime Date { get; set; }
357356
```
358357

359-
**When to use:** Source generators on any .NET version (6+).
358+
**When to use:** System.Text.Json source generator on any .NET version (6+), or reflection-based serialization when you want type-safe format definitions.
360359

361360
---
362361

363362
### `DateTimeConverterResolver` (.NET 9+)
364363

365-
A `JsonSerializerContext` and `IJsonTypeInfoResolver` that enables attribute-based date formatting with source generators by using contract customization.
364+
A `JsonSerializerContext` and `IJsonTypeInfoResolver` that enables attribute-based date formatting with System.Text.Json source generator by using contract customization. Required when using `JsonDateTimeFormatAttribute`.
366365

367366
```csharp
368367
var resolver = new DateTimeConverterResolver(MyJsonContext.Default);
369368
var options = new JsonSerializerOptions { TypeInfoResolver = resolver };
370369
```
371370

372-
**When to use:** .NET 9+ source generators with `JsonDateTimeFormatAttribute` or `JsonDateTimeConverterAttribute`.
371+
**When to use:** .NET 9+ System.Text.Json source generator with `JsonDateTimeFormatAttribute` or `JsonDateTimeConverterAttribute`.
373372

374373
---
375374

@@ -378,9 +377,9 @@ var options = new JsonSerializerOptions { TypeInfoResolver = resolver };
378377
| Scenario | Recommended Approach |
379378
|----------|---------------------|
380379
| Reflection-based, any .NET version | `JsonDateTimeConverterAttribute` |
381-
| Source generator, .NET 6-8 | `JsonDateTimeFormatConverter<T>` |
382-
| Source generator, .NET 9+ (no warnings) | `JsonDateTimeFormatAttribute` + `DateTimeConverterResolver` |
383-
| Source generator, .NET 9+ (backward compat) | `JsonDateTimeConverterAttribute` + `DateTimeConverterResolver` (⚠️ warnings) |
380+
| System.Text.Json source generator, .NET 6-8 | `JsonDateTimeFormatConverter<T>` |
381+
| System.Text.Json source generator, .NET 9+ (no warnings) | `JsonDateTimeFormatAttribute` + `DateTimeConverterResolver` |
382+
| System.Text.Json source generator, .NET 9+ (backward compat) | `JsonDateTimeConverterAttribute` + `DateTimeConverterResolver` (⚠️ warnings) |
384383
| Need reusable formats across many properties | `JsonDateTimeFormatConverter<T>` (define format class once) |
385384
| Prototyping/simple projects | `JsonDateTimeConverterAttribute` (simplest) |
386385
| AOT compilation | `JsonDateTimeFormatConverter<T>` or .NET 9+ resolver with attributes |
@@ -391,7 +390,7 @@ var options = new JsonSerializerOptions { TypeInfoResolver = resolver };
391390

392391
### Source Generator Limitations (.NET 6-8)
393392

394-
`JsonDateTimeConverterAttribute` produces **SYSLIB1223** warning with source generators in .NET 6-8:
393+
`JsonDateTimeConverterAttribute` produces **SYSLIB1223** warning with System.Text.Json source generator in .NET 6-8:
395394

396395
> "Attributes deriving from JsonConverterAttribute are not supported by the source generator."
397396
@@ -401,7 +400,7 @@ var options = new JsonSerializerOptions { TypeInfoResolver = resolver };
401400

402401
### SYSLIB1223 Warning with JsonDateTimeConverterAttribute (.NET 9+ Source Generators)
403402

404-
When using `JsonDateTimeConverterAttribute` with source generators in .NET 9+, you'll get SYSLIB1223 warnings:
403+
When using `JsonDateTimeConverterAttribute` with System.Text.Json source generator in .NET 9+, you'll get SYSLIB1223 warnings:
405404

406405
> "Attributes deriving from JsonConverterAttribute are not supported by the source generator."
407406
@@ -430,13 +429,13 @@ public class Format1 : IJsonDateTimeFormat { public static string Format => "yyy
430429
public class Format2 : IJsonDateTimeFormat { public static string Format => "yyyy-MM-ddTHH:mm:ss"; }
431430
```
432431

433-
This is a limitation of source generators not supporting constructor parameters or static analyzer tricks.
432+
This is a limitation of System.Text.Json source generator not supporting constructor parameters for converters.
434433

435434
---
436435

437436
### .NET 9+ Resolver Requirement
438437

439-
`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.
438+
`DateTimeConverterResolver` **only works on .NET 9+** because, while `JsonPropertyInfo.AttributeProvider` exists in .NET 7-8, it is not populated by System.Text.Json source generator 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.
440439

441440
---
442441

0 commit comments

Comments
 (0)