AvroSourceGenerator 0.7.0

There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package AvroSourceGenerator --version 0.7.0
                    
NuGet\Install-Package AvroSourceGenerator -Version 0.7.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="AvroSourceGenerator" Version="0.7.0">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="AvroSourceGenerator" Version="0.7.0" />
                    
Directory.Packages.props
<PackageReference Include="AvroSourceGenerator">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
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 AvroSourceGenerator --version 0.7.0
                    
#r "nuget: AvroSourceGenerator, 0.7.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 AvroSourceGenerator@0.7.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=AvroSourceGenerator&version=0.7.0
                    
Install as a Cake Addin
#tool nuget:?package=AvroSourceGenerator&version=0.7.0
                    
Install as a Cake Tool

Avro Source Generator

NuGet NuGet (pre-release) License: MIT Build

Avro Source Generator

Avro Source Generator is a modern .NET source generator that produces strongly typed C# models from Avro schema, protocol, and IDL files (.avsc, .avpr, and .avdl). It’s designed to be fast, incremental, and compatible with Apache Avro.

Generated code takes advantage of modern C# language features, including nullable reference types, init-only and required properties, and partial records or classes — ensuring clean, idiomatic C# output.


Prerequisites

  • .NET SDK with Roslyn 4.11 or later, such as .NET SDK 8.0.400 or later. Visual Studio builds require Visual Studio 2022 17.11 or later; see the SDK and Visual Studio version mapping.
  • Optional runtime integration with one of the following Avro libraries:
    • Apache.Avro — official Avro implementation for C#
    • Chr.Avro — designed to serve as a flexible alternative to the Apache implementation

You can use the generator without an Avro library, but library-specific features (e.g., ISpecificRecord) won’t be emitted.


Installation & Basic Usage

Install the package:

dotnet add package AvroSourceGenerator

Mark it as a build-only dependency in your .csproj file:

<PackageReference Include="AvroSourceGenerator"
                  Version="*"
                  PrivateAssets="all"
                  ExcludeAssets="runtime" />

Include your .avsc schema files, .avpr protocol files, and .avdl IDL files as AdditionalFiles:

<ItemGroup>
  <AdditionalFiles Include="schemas/*.avsc" />
  <AdditionalFiles Include="schemas/*.avpr" />
  <AdditionalFiles Include="schemas/*.avdl" />
</ItemGroup>

Add a schema file under schemas/, e.g. schemas/user.avsc:

{
  "type": "record",
  "name": "User",
  "namespace": "example",
  "fields": [
    { "name": "Name", "type": "string" },
    { "name": "Email", "type": ["null", "string"] },
    { "name": "CreatedAt", "type": { "type": "long", "logicalType": "timestamp-millis" } }
  ]
}

Or add an Avro IDL file under schemas/, e.g. schemas/user.avdl:

namespace example;

schema UserFromIdl;

/** Example user */
record UserFromIdl {
    string Name;
    string? Email = null;
    timestamp_ms CreatedAt;
}

The file extension selects the parser: .avsc for JSON schemas, .avpr for JSON protocols, and .avdl for IDL. A protocol supplied as a schema reports AVROSG2000 (schema expected); a schema supplied as a protocol reports AVROSG2001 (protocol expected).

AVDL imports are resolved relative to the importing file. Every imported .avdl, .avsc, or .avpr file, including transitive imports, must also be included explicitly as an <AdditionalFiles> item. Import cycles, missing files, and import kind/file type mismatches are reported as errors. Unused imports produce warnings.

Build your project — the generator will create C# types matching your schemas and IDL definitions.

If an input contains errors, the generator reports diagnostics and continues generating independent valid files. Files that depend on invalid schemas are suppressed until those errors are resolved.


Example Output

For the User schema above, targeting Apache.Avro with C# 12 language features produces (abridged):

// <auto-generated/>
#pragma warning disable CS8618, CS8633, CS8714, CS8775, CS8981
#nullable enable

namespace example;

[global::System.CodeDom.Compiler.GeneratedCode("AvroSourceGenerator", "1.0.0.0")]
public partial record User
{
    public required string Name { get; init; }
    public string? Email { get; init; }
    public required global::System.DateTime CreatedAt { get; init; }
}

partial record User : global::Avro.Specific.ISpecificRecord
{
    global::Avro.Schema global::Avro.Specific.ISpecificRecord.Schema { get => User._SCHEMA; }

    public static readonly global::Avro.Schema _SCHEMA = global::Avro.Schema.Parse("""
    {
      "type": "record",
      "name": "User",
      "namespace": "example",
      "fields": [
        { "name": "Name", "type": "string" },
        { "name": "Email", "type": ["null", "string"] },
        { "name": "CreatedAt", "type": { "type": "long", "logicalType": "timestamp-millis" } }
      ]
    }
    """);

    object? global::Avro.Specific.ISpecificRecord.Get(int fieldPos)
    {
        switch (fieldPos)
        {
            case 0: return this.Name;
            case 1: return this.Email;
            case 2: return this.CreatedAt;
            default: throw new global::Avro.AvroRuntimeException($"Bad index {fieldPos} in Get()");
        }
    }

    void global::Avro.Specific.ISpecificRecord.Put(int fieldPos, object? fieldValue)
    {
        switch (fieldPos)
        {
            case 0:
                Set_Name(this, (string)fieldValue!); break;
                [global::System.Runtime.CompilerServices.UnsafeAccessor(global::System.Runtime.CompilerServices.UnsafeAccessorKind.Method, Name = "set_Name")]
                extern static void Set_Name(global::example.User obj, string value);
            case 1:
                Set_Email(this, fieldValue! is null ? null : (string)fieldValue!); break;
                [global::System.Runtime.CompilerServices.UnsafeAccessor(global::System.Runtime.CompilerServices.UnsafeAccessorKind.Method, Name = "set_Email")]
                extern static void Set_Email(global::example.User obj, string? value);
            case 2:
                Set_CreatedAt(this, (global::System.DateTime)fieldValue!); break;
                [global::System.Runtime.CompilerServices.UnsafeAccessor(global::System.Runtime.CompilerServices.UnsafeAccessorKind.Method, Name = "set_CreatedAt")]
                extern static void Set_CreatedAt(global::example.User obj, global::System.DateTime value);
            default:
                throw new global::Avro.AvroRuntimeException($"Bad index {fieldPos} in Put()");
        }
    }
}
#nullable restore
#pragma warning restore CS8618, CS8633, CS8714, CS8775, CS8981

The exact shape depends on configuration and the selected Avro library.


Samples

The repository samples use the SDK selected by global.json, currently .NET 10. The Kafka samples also require Docker to run their Kafka and Schema Registry containers.

For example, run the Chr.Avro Kafka sample with:

dotnet run --project samples/AvroSourceGenerator.ChrAvroKafka/AvroSourceGenerator.ChrAvroKafka.csproj

Extending Generated Types

Generated records, classes, and variant interfaces are declared as partial, allowing you to add members or behavior. Generated enums cannot be extended with partial declarations.

namespace example;

public partial record User
{
    public override string ToString() => $"{Name} <{Email}>";
}

Configuration

Configure the generator via MSBuild properties in your .csproj file.

Access Modifier

Generated types are public by default. To make them internal:

<PropertyGroup>
  <AvroSourceGeneratorAccessModifier>internal</AvroSourceGeneratorAccessModifier>
</PropertyGroup>

Supported values: public (default), internal.


Record vs Class Generation

By default, types are generated as record when possible. To use class instead:

<PropertyGroup>
  <AvroSourceGeneratorRecordDeclaration>class</AvroSourceGeneratorRecordDeclaration>
</PropertyGroup>

Some schema kinds (e.g., fixed, error for Apache.Avro) require classes due to inheritance constraints.


Language Features

By default, the generator matches the consuming project’s C# version. You can target an older version for broader compatibility:

<PropertyGroup>
  <AvroSourceGeneratorLanguageFeatures>CSharp7_3</AvroSourceGeneratorLanguageFeatures>
</PropertyGroup>

This disables newer features such as records or nullable reference types.

Supported values are CSharp7_3, CSharp8, CSharp9, CSharp10, CSharp11, CSharp12, CSharp13.


Avro Library Selection

The generator tries to detect the Avro library automatically from referenced packages. You can override this behavior by specifying the target library explicitly.

No Supported Package Detected

Code still generates, but without library-specific features. To suppress the warning and explicitly disable integration:

<PropertyGroup>
  <AvroSourceGeneratorAvroLibrary>None</AvroSourceGeneratorAvroLibrary>
</PropertyGroup>
Multiple Supported Packages Detected

Specify one explicitly:

<PropertyGroup>
  <AvroSourceGeneratorAvroLibrary>Apache</AvroSourceGeneratorAvroLibrary>
</PropertyGroup>

Supported values:

  • Auto (default) — detect automatically
  • None — no library-specific code
  • Apache — target Apache.Avro
  • Chr — target Chr.Avro

Apache.Avro Logical Type Compatibility

The Apache target preserves unknown logical-type annotations in generated schema JSON and uses the underlying C# type for their fields. Support depends on the Apache.Avro runtime version: Avro.Schema.Parse in 1.12.1 rejects unknown logical types, which can fail when a generated _SCHEMA field is initialized; 1.12.2 accepts them. The generator does not check the Apache.Avro version, so use a runtime that can parse the logical types in your schemas.

Parsing and serialization support can differ. Apache.Avro 1.12.2 can parse fixed-backed decimal schemas, but its specific-record writer fails when serializing those decimal values. Successful code generation or schema parsing therefore does not guarantee that every logical type can be serialized or accepted by Schema Registry.


Duplicate Resolution

By default, duplicate schema declarations produce an error. A duplicate occurs when Avro input files (.avsc, .avpr, or .avdl) declare the same fully qualified schema name.

This behavior can be configured using the following MSBuild property:

<PropertyGroup>
  <AvroSourceGeneratorDuplicateResolution>Ignore</AvroSourceGeneratorDuplicateResolution>
</PropertyGroup>

Supported values:

  • Error (default) — reports a duplicate-schema diagnostic and suppresses affected files; independent valid files still generate.
  • Ignore — keeps the first declaration in the supplied file order and ignores later declarations with the same name in other files.

Duplicate declarations within the same file are always errors, including when Ignore is selected. Including the same file through equivalent source paths also produces a duplicate-source-path error.

With Ignore, input order determines which definition is used. Use it only when duplicate declarations are intentional and safe.


Reference Resolution

By default, the generator follows Avro's schema resolution rules and requires named schemas to be defined before they are referenced.

If your project keeps related schemas in separate Avro input files, you can defer reference checks until all supported inputs have been read:

<PropertyGroup>
  <AvroSourceGeneratorReferenceResolution>Deferred</AvroSourceGeneratorReferenceResolution>
</PropertyGroup>

Supported values:

  • Strict (default) — references must resolve to an earlier declaration in the same file or to a declaration in the file's transitive AVDL import closure
  • Deferred — unresolved references are collected and resolved after all .avsc, .avpr, and .avdl inputs are read; declared import paths are still validated

Contributing

Contributions are welcome! If you encounter bugs, want to propose features, or improve docs, please open an issue or submit a pull request on GitHub.


License

Licensed under the MIT License.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.0

    • No dependencies.

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
0.8.0-preview.4.main.16 49 10/14/2026
0.8.0-preview.3.main.14 54 10/13/2026
0.8.0-preview.2.main.11 59 10/11/2026
0.8.0-preview.1.main.7 48 10/9/2026
0.7.0 488 10/1/2026
0.7.0-preview.4.main.61 81 9/25/2026
0.7.0-preview.3.main.32 87 7/29/2026
0.7.0-preview.2.main.21 102 6/2/2026
0.7.0-preview.1.main.18 128 3/16/2026
0.6.0 102,958 1/29/2026
0.6.0-preview.3.main.12 109 1/24/2026
0.6.0-preview.2.main.10 124 1/23/2026
0.6.0-preview.1.main.9 110 1/23/2026
0.5.3 350 1/14/2026
0.5.2 280 1/13/2026
0.5.2-preview.1.duplicate-r... 1,289 12/9/2025
0.5.1 18,283 12/7/2025
0.5.0 43,375 12/4/2025
0.4.0 1,474 11/6/2025
0.4.0-preview.2 191 10/15/2025
Loading failed