System.Text.Json SourceGenerator should have better docs and public API
- Dominant language
- No language data
- Stars
- 4.8k
- Forks
- 6.1k
- Avg merge
- 15h 21m
- Merged PRs (30d)
- 370
Description
(I apologize in advance if this is the wrong place for such kind of feedback. If so, would appreciate any advice where to put this)
## Docs issue
The following two links are basically the only docs on JSON source generators:
- [How to use source generation in System.Text.Json](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation)
- [Try the new System.Text.Json source generator](https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-source-generator/)
The issue is that they describe one simple class consisting of basic .net types (e. g. integers or bools) that is nowhere near the real-world usage. Web APIs have a lot of DTOs (data transfer objects) which are used in multiple ways in controllers (get, put, etc.) and can be nested.
Here are just a handful of questions that are not answered in docs:
1. Suppose one has dozens (or hundreds) DTOs in Web API. How one should add source gen for them? One context with dozens (hunderds) of attributes for each DTO? Separate contexts? Should I have source gen for all DTOs or only some?
It would be great to see an example with at least 2-3 DTOs, not a single `WeatherForecast`. And guidelines/tips how to add source generation for the entire API with dozens (hundreds) of DTOs.
2. What to do with nested DTOs. E. g. `AddressDto` inside `PersonDto`. How to configure source gen for that case? What would happen if nested DTO doesn’t have source gen but a parent does? What would happen if parent DTO has source gen, but nested doesn’t? What if I have a DTO that has 3 nested levels: `CompanyDto` that has `EmployeeDto[]` where each one has `AddressDto`, and source gen is configured only for `CompanyDto` and `AddressDto`?
3. How one should handle collections of different types? What types of collections should be marked for source generation? Suppose I have these 3 cases:
- nested `IReadOnlyCollection Addresses` property inside `PersonDto`;
- some controller to GET addresses that returns `ActionResult>`;
- some controller to POST `AddressDto`.
Should I add to source gen all three: `IReadOnlyCollection`, `IEnumerable`, `AddressDto`? Or if just `IEnumerable` and`AddressDto` would suffice?
4. What about controller action return type `Task>>`: what should be added in this case for source gen? What if the actual variable that is returned inside the controller is `List` or `HashSet` (while the controller’s action method signature is `Task>>`) = will the `IEnumerable` mentioned in source-gen suffice?
5. Is there any way to know if some cases are missed? E. g. if `OrderDto` is added, but `IEnumerable` is not? To paraphrase, is there any way have some warnings during at least runtime(?) if reflection instead of source gen stuff have been used for (de)serialization in API controllers.
## Overall UX thoughts
One would think who would not like to have free performance gains of using JSON source gen in Web APIs. Unfortunately current implementation feels like something one should wait for better times before implementing in their code. Something that was half-baked and rushed as a need for some specific case and that is not ready for actual API projects — too much manual boilerplate and not error-prone. Though I may be proven utterly wrong given more detailed docs/guides emerge.
One could ask for an option to apply `JsonSerializable` attributes directly to DTO classes instead of some separate context, or many other things like not having to think about collections (e. g. adding OrderDto would automatically handle cases for IEnumerable).
Of course, ideal case would be not to think about this at all. One possible solution is to have another source generator or T4 template (akin to Entity Framework DB first) that would automatically generate required “json source generator” boilerplate for all .cs files located inside project DTO folder. Is it really the intended way to manually write hundreds of `[JsonSerializable(typeof(insert_every_dto_type_name_here_and_collection_permutation))]`?
---
#### Document Details
⚠ *Do not edit this section. It is required for learn.microsoft.com ➟ GitHub issue linking.*
* ID: ee53c3dc-df79-82ef-ce25-3233ff292c55
* Version Independent ID: 558903e9-8173-464e-ff8b-7744419ad7e4
* Content: [How to use source generation in System.Text.Json - .NET](https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation?pivots=dotnet-8-0)
* Content Source: [docs/standard/serialization/system-text-json/source-generation.md](https://github.com/dotnet/docs/blob/main/docs/standard/serialization/system-text-json/source-generation.md)
* Product: **dotnet-fundamentals**
* GitHub Login: @gewarren
* Microsoft Alias: **gewarren**
Contributor guide
Assessment
This issue has not been assessed yet.