Skip to content

Commit ecfa05d

Browse files
CopilotScarletKuro
andcommitted
Add comprehensive README.md and AGENT.md documentation
Co-authored-by: ScarletKuro <19953225+ScarletKuro@users.noreply.github.com>
1 parent ffa2ce5 commit ecfa05d

2 files changed

Lines changed: 674 additions & 77 deletions

File tree

AGENT.md

Lines changed: 362 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,362 @@
1+
# AGENT.md
2+
3+
This document provides guidance for AI agents and developers working on the **Scarlet.System.Text.Json.DateTimeConverter** package.
4+
5+
## Package Overview
6+
7+
**Scarlet.System.Text.Json.DateTimeConverter** is a .NET library that provides flexible custom date/time formatting for `System.Text.Json` serialization. It supports both reflection-based and source generator approaches, with special .NET 9+ features for enhanced source generator compatibility.
8+
9+
### Key Features
10+
11+
- Custom date/time format attributes (`JsonDateTimeConverterAttribute`)
12+
- Source generator-compatible format converters (`JsonDateTimeFormatConverter<T>`)
13+
- .NET 9+ contract customization resolver (`DateTimeConverterResolver`)
14+
- Support for `DateTime`, `DateTimeOffset`, and nullable variants
15+
- Multi-target framework support (.NET 6, 7, 8, 9, 10)
16+
17+
## Repository Structure
18+
19+
```
20+
Scarlet.System.Text.Json.DateTimeConverter/
21+
├── README.md # User-facing documentation
22+
├── LICENSE # MIT License
23+
├── version.json # Nerdbank.GitVersioning configuration
24+
├── icon.png # Package icon
25+
├── build/ # NUKE build system
26+
│ ├── Build.cs # Main build configuration
27+
│ └── _build.csproj # Build project
28+
├── src/
29+
│ ├── Scarlet.System.Text.Json.DateTimeConverter/
30+
│ │ ├── Converters/ # Internal converter implementations
31+
│ │ │ ├── DateTimeConverter.cs
32+
│ │ │ ├── DateTimeNullableConverter.cs
33+
│ │ │ ├── DateTimeOffsetConverter.cs
34+
│ │ │ └── DateTimeOffsetNullableConverter.cs
35+
│ │ ├── DateTimeConverterFactoryHelper.cs
36+
│ │ ├── DateTimeConverterResolver.cs # .NET 9+ contract customization
37+
│ │ ├── IJsonDateTimeFormat.cs
38+
│ │ ├── JsonDateTimeConverterAttribute.cs
39+
│ │ ├── JsonDateTimeFormatConverter.cs
40+
│ │ └── Scarlet.System.Text.Json.DateTimeConverter.csproj
41+
│ └── Scarlet.System.Text.Json.DateTimeConverter.Tests/
42+
│ ├── JsonDateTimeConverterAttributeTests.cs
43+
│ ├── JsonDateTimeFormatConverterTests.cs
44+
│ ├── Model/ # Test models
45+
│ │ ├── ReflectionBasedModel.cs
46+
│ │ ├── SourceGeneratorModel.cs
47+
│ │ ├── SourceGeneratorWithResolverModel.cs
48+
│ │ └── TestModelSourceGeneratorJsonSerializerContext.cs
49+
│ └── Scarlet.System.Text.Json.DateTimeConverter.Tests.csproj
50+
└── .github/
51+
└── workflows/ # CI/CD workflows
52+
├── continuous.yml # Build and test on push
53+
└── release.yml # Publish on tag
54+
```
55+
56+
## Building the Project
57+
58+
### Prerequisites
59+
60+
- .NET SDK 10.0 or later (for development)
61+
- Git (for version control)
62+
63+
### Build Commands
64+
65+
The project uses [NUKE](https://nuke.build/) for build automation.
66+
67+
#### Quick Build
68+
69+
```bash
70+
# Linux/macOS
71+
./build.sh Compile
72+
73+
# Windows
74+
build.cmd Compile
75+
```
76+
77+
#### Clean Build
78+
79+
```bash
80+
# Clean + Restore + Build
81+
./build.sh Clean Compile
82+
83+
# Or use standard dotnet commands
84+
dotnet clean
85+
dotnet build src/Scarlet.System.Text.Json.DateTimeConverter.sln --configuration Release
86+
```
87+
88+
#### Full CI Build
89+
90+
```bash
91+
./build.sh Clean Restore VerifyFormat Compile Test Pack
92+
```
93+
94+
### Build Targets
95+
96+
| Target | Description |
97+
|--------|-------------|
98+
| `Clean` | Cleans build artifacts |
99+
| `Restore` | Restores NuGet packages |
100+
| `VerifyFormat` | Verifies code formatting (whitespace and style) |
101+
| `Compile` | Compiles the solution |
102+
| `Test` | Runs all tests |
103+
| `Pack` | Creates NuGet packages |
104+
| `Push` | Pushes packages to NuGet.org (requires tag + secrets) |
105+
| `PushGithubNuget` | Pushes packages to GitHub Packages (requires tag + secrets) |
106+
107+
## Running Tests
108+
109+
### Run All Tests
110+
111+
```bash
112+
# Using NUKE
113+
./build.sh Test
114+
115+
# Using dotnet CLI
116+
dotnet test src/Scarlet.System.Text.Json.DateTimeConverter.Tests/Scarlet.System.Text.Json.DateTimeConverter.Tests.csproj --configuration Release
117+
```
118+
119+
### Run Specific Test
120+
121+
```bash
122+
dotnet test --filter "FullyQualifiedName~ReflectionBased_DateTime_WithAttribute"
123+
```
124+
125+
### Test Project Structure
126+
127+
Tests are organized into two main test classes:
128+
129+
1. **`JsonDateTimeConverterAttributeTests.cs`**
130+
- Tests for `JsonDateTimeConverterAttribute` with reflection-based serialization
131+
- Tests individual primitive types and complete models
132+
133+
2. **`JsonDateTimeFormatConverterTests.cs`**
134+
- Tests for `JsonDateTimeFormatConverter<T>` with both reflection and source generators
135+
- Tests for `DateTimeConverterResolver` (.NET 9+)
136+
- Includes tests with null values
137+
138+
### Test Naming Convention
139+
140+
Tests follow the pattern: `[ApproachType]_[Scenario]_[OptionalDetails]`
141+
142+
Examples:
143+
- `ReflectionBased_DateTime_WithAttribute`
144+
- `SourceGenerator_CompleteModel_WithFormatConverter`
145+
- `SourceGenerator_WithResolver_WithAttribute_UsingOptions`
146+
147+
## Development Workflow
148+
149+
### 1. Make Changes
150+
151+
Edit source files in `src/Scarlet.System.Text.Json.DateTimeConverter/`
152+
153+
### 2. Format Code
154+
155+
The project enforces code formatting. Use:
156+
157+
```bash
158+
# Check format
159+
dotnet format whitespace src/Scarlet.System.Text.Json.DateTimeConverter.sln --verify-no-changes
160+
dotnet format style src/Scarlet.System.Text.Json.DateTimeConverter.sln --verify-no-changes
161+
162+
# Fix format
163+
dotnet format whitespace src/Scarlet.System.Text.Json.DateTimeConverter.sln
164+
dotnet format style src/Scarlet.System.Text.Json.DateTimeConverter.sln
165+
```
166+
167+
### 3. Build and Test
168+
169+
```bash
170+
./build.sh Compile Test
171+
```
172+
173+
### 4. Create PR
174+
175+
The project uses a standard GitHub workflow:
176+
1. Fork or create a branch
177+
2. Make changes
178+
3. Ensure tests pass
179+
4. Create pull request
180+
181+
## Architecture
182+
183+
### Core Components
184+
185+
#### 1. Converters (Internal)
186+
187+
Four internal converter classes handle actual JSON serialization/deserialization:
188+
- `DateTimeConverter` - for `DateTime`
189+
- `DateTimeNullableConverter` - for `DateTime?`
190+
- `DateTimeOffsetConverter` - for `DateTimeOffset`
191+
- `DateTimeOffsetNullableConverter` - for `DateTimeOffset?`
192+
193+
All use `CultureInfo.InvariantCulture` for consistent formatting.
194+
195+
#### 2. Public API
196+
197+
**`JsonDateTimeConverterAttribute`**
198+
```csharp
199+
[JsonDateTimeConverter("yyyy-MM-dd")]
200+
public DateTime Date { get; set; }
201+
```
202+
- Derives from `JsonConverterAttribute`
203+
- Works with reflection-based serialization
204+
- .NET 9+: Works with source generators via `DateTimeConverterResolver`
205+
206+
**`JsonDateTimeFormatConverter<T>`**
207+
```csharp
208+
[JsonConverter(typeof(JsonDateTimeFormatConverter<MyFormat>))]
209+
public DateTime Date { get; set; }
210+
```
211+
- `JsonConverterFactory` implementation
212+
- Compatible with source generators (all .NET versions)
213+
- Requires `IJsonDateTimeFormat` implementation
214+
215+
**`DateTimeConverterResolver` (.NET 9+)**
216+
```csharp
217+
var options = new JsonSerializerOptions
218+
{
219+
TypeInfoResolver = new DateTimeConverterResolver(MyJsonContext.Default)
220+
};
221+
```
222+
- Implements `IJsonTypeInfoResolver` and extends `JsonSerializerContext`
223+
- Uses `JsonPropertyInfo.AttributeProvider` to read attributes
224+
- Enables attribute syntax with source generators
225+
226+
#### 3. Factory Helper
227+
228+
`DateTimeConverterFactoryHelper` centralizes converter instantiation based on target type.
229+
230+
### Multi-Targeting
231+
232+
The library targets multiple frameworks to maximize compatibility:
233+
234+
```xml
235+
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
236+
```
237+
238+
`DateTimeConverterResolver` is conditionally compiled for .NET 9+ only:
239+
240+
```csharp
241+
#if NET9_0_OR_GREATER
242+
public class DateTimeConverterResolver : JsonSerializerContext, IJsonTypeInfoResolver
243+
{
244+
// Implementation
245+
}
246+
#endif
247+
```
248+
249+
### Testing Strategy
250+
251+
Tests verify three distinct usage patterns:
252+
253+
1. **Reflection-based** - Uses `JsonDateTimeConverterAttribute` with default `JsonSerializer`
254+
2. **Source generator with converter** - Uses `JsonDateTimeFormatConverter<T>` with `JsonSerializerContext`
255+
3. **Source generator with resolver** - Uses `JsonDateTimeConverterAttribute` + `DateTimeConverterResolver` (.NET 9+)
256+
257+
Each pattern is tested with:
258+
- Individual types (`DateTime`, `DateTime?`, `DateTimeOffset`, `DateTimeOffset?`)
259+
- Complete models
260+
- Null value handling
261+
262+
## Common Tasks
263+
264+
### Adding a New Converter
265+
266+
1. Create converter in `Converters/` directory
267+
2. Implement `JsonConverter<T>` with `Read` and `Write` methods
268+
3. Register in `DateTimeConverterFactoryHelper.CreateConverter`
269+
4. Add tests in both test files
270+
5. Update documentation
271+
272+
### Updating Supported Frameworks
273+
274+
1. Update `<TargetFrameworks>` in `.csproj`
275+
2. Test all scenarios on new framework
276+
3. Update `README.md` prerequisites
277+
4. Update CI/CD workflows if needed
278+
279+
### Releasing a New Version
280+
281+
Versioning is handled by [Nerdbank.GitVersioning](https://github.com/dotnet/Nerdbank.GitVersioning):
282+
283+
1. Update `version.json` if needed
284+
2. Create a git tag: `git tag 1.2.0`
285+
3. Push tag: `git push origin 1.2.0`
286+
4. GitHub Actions will automatically build and publish
287+
288+
## Troubleshooting
289+
290+
### Build Issues
291+
292+
**Problem:** "Shallow clone lacks the objects required to calculate version height"
293+
294+
**Solution:**
295+
```bash
296+
git fetch --unshallow
297+
```
298+
299+
**Problem:** Format verification fails
300+
301+
**Solution:**
302+
```bash
303+
dotnet format whitespace src/Scarlet.System.Text.Json.DateTimeConverter.sln
304+
dotnet format style src/Scarlet.System.Text.Json.DateTimeConverter.sln
305+
```
306+
307+
### Test Issues
308+
309+
**Problem:** SYSLIB1223 warning in tests
310+
311+
**Solution:** This is expected for `SourceGeneratorWithResolverModel` as it demonstrates the problem that `DateTimeConverterResolver` solves.
312+
313+
**Problem:** Tests fail after renaming models
314+
315+
**Solution:** Ensure all references are updated in both test files and `TestModelSourceGeneratorJsonSerializerContext.cs`.
316+
317+
## CI/CD
318+
319+
### Continuous Integration
320+
321+
On every push:
322+
- Restore packages
323+
- Verify code format
324+
- Compile all target frameworks
325+
- Run tests
326+
- Create NuGet packages (artifacts)
327+
328+
### Release
329+
330+
On tag push (e.g., `1.2.0`):
331+
- All CI steps
332+
- Publish to NuGet.org
333+
- Publish to GitHub Packages
334+
335+
### Secrets Required
336+
337+
- `NUGET_KEY` - NuGet.org API key
338+
- `GITHUB_TOKEN` - Automatically provided by GitHub Actions
339+
340+
## Code Style
341+
342+
- Use C# 12+ features where appropriate
343+
- Nullable reference types enabled
344+
- `ImplicitUsings` enabled
345+
- Follow .editorconfig rules
346+
- Use XML documentation for public APIs
347+
- Keep internal converters simple and focused
348+
349+
## Performance Considerations
350+
351+
- Converters use `CultureInfo.InvariantCulture` for consistent, culture-independent formatting
352+
- No reflection in hot path (converters are created once and reused)
353+
- Source generator support ensures zero reflection overhead when using AOT
354+
355+
## Additional Resources
356+
357+
- [System.Text.Json Documentation](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/overview)
358+
- [Custom Converters](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/converters-how-to)
359+
- [Source Generation](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation)
360+
- [Contract Customization (.NET 9+)](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/custom-contracts)
361+
- [NUKE Build](https://nuke.build/)
362+
- [Nerdbank.GitVersioning](https://github.com/dotnet/Nerdbank.GitVersioning)

0 commit comments

Comments
 (0)