Weboost.SchemaAnnotations 1.0.0

dotnet add package Weboost.SchemaAnnotations --version 1.0.0
                    
NuGet\Install-Package Weboost.SchemaAnnotations -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Weboost.SchemaAnnotations" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Weboost.SchemaAnnotations" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Weboost.SchemaAnnotations" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Weboost.SchemaAnnotations --version 1.0.0
                    
#r "nuget: Weboost.SchemaAnnotations, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Weboost.SchemaAnnotations@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Weboost.SchemaAnnotations&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Weboost.SchemaAnnotations&version=1.0.0
                    
Install as a Cake Tool

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 (internal too with IncludeInternal = 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: doc for documented members.
  • Positional record <param> docs become the property descriptions.
  • <inheritdoc/> is followed through overrides, interface implementations, base types and cref targets. 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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