Weboost.SchemaAnnotations
1.0.0
dotnet add package Weboost.SchemaAnnotations --version 1.0.0
NuGet\Install-Package Weboost.SchemaAnnotations -Version 1.0.0
<PackageReference Include="Weboost.SchemaAnnotations" Version="1.0.0" />
<PackageVersion Include="Weboost.SchemaAnnotations" Version="1.0.0" />
<PackageReference Include="Weboost.SchemaAnnotations" />
paket add Weboost.SchemaAnnotations --version 1.0.0
#r "nuget: Weboost.SchemaAnnotations, 1.0.0"
#:package Weboost.SchemaAnnotations@1.0.0
#addin nuget:?package=Weboost.SchemaAnnotations&version=1.0.0
#tool nuget:?package=Weboost.SchemaAnnotations&version=1.0.0
Weboost.SchemaAnnotations
Turns C# /// XML doc summaries into description annotations in the JSON schemas Microsoft.Extensions.AI
builds for tools and structured output (AIJsonSchemaCreateOptions), and in schemas produced by
System.Text.Json.Schema.JsonSchemaExporter. The Weboost.SchemaAnnotations.Generator source generator
collects the summaries at compile time into a frozen lookup, so nothing reads .xml files or reflects
over documentation at runtime. AOT and trimming safe, works with reflection-based and source-generated
JsonSerializerContext.
Install
<PackageReference Include="Weboost.SchemaAnnotations" Version="*" />
The package ships the runtime library and the source generator together. XML doc comments are only visible to the compiler when documentation output is on:
<GenerateDocumentationFile>true</GenerateDocumentationFile>
Without it the generator reports WSA002 and finds nothing.
Configure
One static partial class per assembly carries the configuration as attributes:
using Weboost.SchemaAnnotations;
[SchemaAnnotations(Namespace = "My.Contracts", IncludeInternal = false)] // this assembly, both settings optional
[IncludeSchemaAnnotations(typeof(Billing.Invoice))] // plus the assembly containing Invoice
public static partial class ContractAnnotations;
The generator adds to the class:
| Member | Purpose |
|---|---|
Source |
FrozenSchemaAnnotationSource with every documented public type, property and field of this assembly. |
Annotator |
SchemaAnnotator over Source and the sources of all included assemblies. |
TransformSchemaNode(...) |
Two overloads matching JsonSchemaExporterOptions.TransformSchemaNode and AIJsonSchemaCreateOptions.TransformSchemaNode. |
JsonSchemaExporterOptions.Annotated |
Static extension property: default exporter options plus annotations. |
AIJsonSchemaCreateOptions.Annotated |
Static extension property: default M.E.AI options plus annotations. |
The two Annotated properties need C# 14 (the default for net10.0) and exactly one marked top-level
static class per assembly; otherwise the generator reports WSA007 and you use TransformSchemaNode.
Use
Ready-made options. Reads like the framework's own JsonSchemaExporterOptions.Default:
JsonSchemaExporter.GetJsonSchemaAsNode(MyContext.Default.Options, typeof(Lead), JsonSchemaExporterOptions.Annotated);
AIFunctionFactory.Create(QualifyLead, new AIFunctionFactoryOptions
{
SerializerOptions = MyContext.Default.Options,
JsonSchemaCreateOptions = AIJsonSchemaCreateOptions.Annotated,
});
Your own options. Assign the generated method group; overload resolution picks the right context type:
var options = new AIJsonSchemaCreateOptions
{
IncludeSchemaKeyword = true,
TransformSchemaNode = ContractAnnotations.TransformSchemaNode,
};
// composing with an existing transform
TransformSchemaNode = (ctx, node) => MyTransform(ctx, ContractAnnotations.TransformSchemaNode(ctx, node))
[Description] attributes and any description already present on a node win over the XML summary.
Other schema pipelines can call ContractAnnotations.Annotator.Transform(typeInfo, propertyInfo, node) directly.
Including other assemblies
The generator sees only the compilation it runs in, so each DTO assembly needs its own [SchemaAnnotations]
class. [IncludeSchemaAnnotations(typeof(AnyTypeInThatAssembly))] chains that assembly's Source into
Annotator. This works because the generator stamps every assembly it processes with
[assembly: SchemaAnnotationSource(typeof(...))] and resolves the stamp from the referenced assembly's
metadata. The included class must be public.
Referencing an assembly that was not compiled with the generator reports WSA004; an internal class
reports WSA005. Assemblies whose XML docs you cannot compile (third-party packages) are not supported yet.
What gets collected
- Public classes, structs, interfaces and enums (
internaltoo withIncludeInternal = true), including nested types. - Public non-static properties without parameters and public non-static, non-const fields, declared on the type itself. Inherited members resolve through their declaring type at runtime.
- Enums: the type summary followed by
Member: doc; Member: docfor documented members. - Positional record
<param>docs become the property descriptions. <inheritdoc/>is followed through overrides, interface implementations, base types andcreftargets. An undocumented member also inherits from these sources.<see cref>renders as the qualified name without prefix and arity,<see langword>as the keyword,<para>as a space,<c>and<code>as their text. Other markup is dropped.
Generic types are stored as open generics, so Page<Lead> finds Page<T>. Nullable value types resolve
to their underlying type. Boolean true schemas (custom converters) become { "description": "..." }.
Diagnostics
| Id | Severity | Meaning |
|---|---|---|
| WSA001 | Error | The [SchemaAnnotations] class is not partial. |
| WSA002 | Warning | GenerateDocumentationFile is off. |
| WSA003 | Info | No documented types were found for the marked class. |
| WSA004 | Warning | An included assembly has no generated annotation source. |
| WSA005 | Warning | An included annotation class is not public. |
| WSA006 | Info | [IncludeSchemaAnnotations] points at the current assembly, which is always included. |
| WSA007 | Info | The Annotated extension properties were not generated (class not static, nested, C# < 14, or several marked classes). |
Developing against the repository
When project-referencing instead of using the package, add the generator as an analyzer yourself:
<ProjectReference Include="../Weboost.SchemaAnnotations/Weboost.SchemaAnnotations.csproj" />
<ProjectReference Include="../Weboost.SchemaAnnotations.Generator/Weboost.SchemaAnnotations.Generator.csproj"
ReferenceOutputAssembly="false" OutputItemType="Analyzer" />
Build, test and pack:
dotnet build src/Weboost.SchemaAnnotations.sln -warnaserror
dotnet test --solution src/Weboost.SchemaAnnotations.sln
dotnet pack src/Weboost.SchemaAnnotations -c Release
dotnet publish src/Weboost.SchemaAnnotations.Sample -c Release -r linux-x64
dotnet slopwatch analyze
Releases are cut by pushing a v* tag on main (for example v0.1.0); the version is derived from the tag
by MinVer and the release workflow pushes the package to NuGet.org via trusted publishing.
Generator snapshot tests live in src/Weboost.SchemaAnnotations.Generator.Tests/Snapshots. On a mismatch a
.received.txt is written next to the .verified.txt; run with WEBOOST_ACCEPT_SNAPSHOTS=1 to accept.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.AI.Abstractions (>= 10.10.0)
-
net9.0
- Microsoft.Extensions.AI.Abstractions (>= 10.10.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 73 | 9/15/2026 |