Skip to content

Commit 4c3f23e

Browse files
CopilotScarletKuro
andcommitted
Update documentation to clarify three approaches and specify System.Text.Json source generator
Co-authored-by: ScarletKuro <19953225+ScarletKuro@users.noreply.github.com>
1 parent 7a57fcb commit 4c3f23e

1 file changed

Lines changed: 31 additions & 29 deletions

File tree

README.md

Lines changed: 31 additions & 29 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

@@ -41,10 +40,10 @@ dotnet add package Scarlet.System.Text.Json.DateTimeConverter
4140
## Prerequisites
4241

4342
- **.NET 6+** for basic functionality
44-
- **.NET 9+** for `DateTimeConverterResolver` (source generator attribute support)
43+
- **.NET 9+** for `DateTimeConverterResolver` (System.Text.Json source generator attribute support)
4544

46-
| Target Framework | Reflection + Attribute | Source Generator + Converter | Source Generator + Attribute + Resolver |
47-
|-----------------|:---------------------:|:---------------------------:|:--------------------------------------:|
45+
| Target Framework | Reflection + Attribute | System.Text.Json Source Generator + Converter | System.Text.Json Source Generator + Attribute + Resolver |
46+
|-----------------|:---------------------:|:------------------------------------------:|:------------------------------------------------------:|
4847
| .NET 6, 7, 8 ||||
4948
| .NET 9, 10+ ||||
5049

@@ -63,7 +62,7 @@ var json = JsonSerializer.Serialize(new MyModel { Date = DateTime.Now });
6362
// Output: {"Date":"2026-01-15"}
6463
```
6564

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

6867
```csharp
6968
public class MyModel
@@ -142,7 +141,7 @@ var deserializedOrder = JsonSerializer.Deserialize<Order>(json);
142141

143142
### Source Generator with Format Converter (.NET 6+)
144143

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

147146
```csharp
148147
using Scarlet.System.Text.Json.DateTimeConverter;
@@ -218,9 +217,11 @@ var deserializedOrder = (Order?)JsonSerializer.Deserialize(json, typeof(Order),
218217
```
219218

220219
**✅ Pros:**
221-
- Works with source generators (AOT-friendly)
220+
- Works with System.Text.Json source generator (AOT-friendly)
221+
- Also works with reflection-based serialization
222222
- Compatible with all .NET versions (6+)
223223
- Type-safe format definitions
224+
- Does not require `DateTimeConverterResolver`
224225

225226
**❌ Cons:**
226227
- Requires defining a class for each date format
@@ -231,7 +232,7 @@ var deserializedOrder = (Order?)JsonSerializer.Deserialize(json, typeof(Order),
231232

232233
### Source Generator with Resolver (.NET 9+)
233234

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

236237
#### Option A: JsonDateTimeFormatAttribute (Recommended - No Warnings)
237238

@@ -281,18 +282,19 @@ var deserializedOrder = (Order?)JsonSerializer.Deserialize(json, typeof(Order),
281282
```
282283

283284
**✅ Pros:**
284-
- Clean attribute syntax with source generators
285+
- Clean attribute syntax with System.Text.Json source generator
285286
- AOT-friendly
286287
- **No SYSLIB1223 warnings**
287288
- Best of both worlds: readability + performance
288289

289290
**❌ Cons:**
290291
- **Requires .NET 9+**
292+
- Requires using `DateTimeConverterResolver` to wrap the context
291293
- Slightly more setup (need to wrap context with resolver)
292294

293295
#### Option B: JsonDateTimeConverterAttribute (Backward Compatible - Has Warnings)
294296

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

297299
```csharp
298300
public class Order
@@ -302,7 +304,7 @@ public class Order
302304
}
303305
```
304306

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

307309
**✅ Pros:**
308310
- Works with existing code using `JsonDateTimeConverterAttribute`
@@ -325,26 +327,26 @@ A `JsonConverterAttribute`-derived attribute for specifying date formats directl
325327
public DateTime Date { get; set; }
326328
```
327329

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

330332
---
331333

332334
### `JsonDateTimeFormatAttribute` (.NET 9+)
333335

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

336338
```csharp
337339
[JsonDateTimeFormat("yyyy-MM-dd")]
338340
public DateTime Date { get; set; }
339341
```
340342

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

343345
---
344346

345347
### `JsonDateTimeFormatConverter<T>`
346348

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

349351
```csharp
350352
public class MyFormat : IJsonDateTimeFormat
@@ -356,20 +358,20 @@ public class MyFormat : IJsonDateTimeFormat
356358
public DateTime Date { get; set; }
357359
```
358360

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

361363
---
362364

363365
### `DateTimeConverterResolver` (.NET 9+)
364366

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

367369
```csharp
368370
var resolver = new DateTimeConverterResolver(MyJsonContext.Default);
369371
var options = new JsonSerializerOptions { TypeInfoResolver = resolver };
370372
```
371373

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

374376
---
375377

@@ -378,9 +380,9 @@ var options = new JsonSerializerOptions { TypeInfoResolver = resolver };
378380
| Scenario | Recommended Approach |
379381
|----------|---------------------|
380382
| 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) |
383+
| System.Text.Json source generator, .NET 6-8 | `JsonDateTimeFormatConverter<T>` |
384+
| System.Text.Json source generator, .NET 9+ (no warnings) | `JsonDateTimeFormatAttribute` + `DateTimeConverterResolver` |
385+
| System.Text.Json source generator, .NET 9+ (backward compat) | `JsonDateTimeConverterAttribute` + `DateTimeConverterResolver` (⚠️ warnings) |
384386
| Need reusable formats across many properties | `JsonDateTimeFormatConverter<T>` (define format class once) |
385387
| Prototyping/simple projects | `JsonDateTimeConverterAttribute` (simplest) |
386388
| AOT compilation | `JsonDateTimeFormatConverter<T>` or .NET 9+ resolver with attributes |
@@ -391,7 +393,7 @@ var options = new JsonSerializerOptions { TypeInfoResolver = resolver };
391393

392394
### Source Generator Limitations (.NET 6-8)
393395

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

396398
> "Attributes deriving from JsonConverterAttribute are not supported by the source generator."
397399
@@ -401,7 +403,7 @@ var options = new JsonSerializerOptions { TypeInfoResolver = resolver };
401403

402404
### SYSLIB1223 Warning with JsonDateTimeConverterAttribute (.NET 9+ Source Generators)
403405

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

406408
> "Attributes deriving from JsonConverterAttribute are not supported by the source generator."
407409
@@ -430,13 +432,13 @@ public class Format1 : IJsonDateTimeFormat { public static string Format => "yyy
430432
public class Format2 : IJsonDateTimeFormat { public static string Format => "yyyy-MM-ddTHH:mm:ss"; }
431433
```
432434

433-
This is a limitation of source generators not supporting constructor parameters or static analyzer tricks.
435+
This is a limitation of System.Text.Json source generator not supporting constructor parameters or static analyzer tricks.
434436

435437
---
436438

437439
### .NET 9+ Resolver Requirement
438440

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.
441+
`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.
440442

441443
---
442444

0 commit comments

Comments
 (0)