A fast, opinionated C# code generator for OpenAPI specifications.
Documentation • Installation • Quick Start • Changelog
OpenAPI Code Generator transforms OpenAPI 3.x specifications into clean, modern C# code — generating records, enums, and primitive type aliases with full nullable reference type support and built-in System.Text.Json attributes and converters where needed.
- Modern C# output — Generates
recordtypes with init-only properties - OpenAPI 3.x support — JSON and YAML specifications
- Nullable reference types — Full
#nullable enablesupport - System.Text.Json — Built-in
[JsonPropertyName]and[JsonConverter]attributes - String enums — Generates
[JsonStringEnumConverter]backed enums - Immutable collections —
IReadOnlyList<T>andIReadOnlyDictionary<string, T>by default - Composition support — Handles
allOf,oneOf, andanyOfschemas - URL input — Fetch and generate directly from remote OpenAPI specs
- Zero dependencies at runtime — Generated code only needs
System.Text.Json
Install as a global .NET tool:
dotnet tool install --global Nikcio.OpenApiCodeGenOr as a local tool in your project:
dotnet new tool-manifest
dotnet tool install Nikcio.OpenApiCodeGenGenerate C# models from a local spec file:
openapi-codegen petstore.yaml -o Models.csGenerate from a remote URL with a custom namespace:
openapi-codegen https://petstore3.swagger.io/api/v3/openapi.json -o PetStore.cs -n MyApp.ModelsOutput to stdout:
openapi-codegen spec.yamlUSAGE:
openapi-codegen [OPTIONS] <input> [output]
openapi-codegen --input <file-or-url> --output <file>
ARGUMENTS:
<input> Path or URL to an OpenAPI specification (JSON or YAML)
[output] Output file path (defaults to stdout)
OPTIONS:
-i, --input <path> Input OpenAPI spec file or URL
-o, --output <path> Output C# file path
-n, --namespace <name> C# namespace (default: GeneratedModels)
--model-prefix <prefix> Prefix every generated model type name
--include-schema <name> Include only the named schema and its dependencies (repeatable)
--no-doc-comments Disable XML doc comment generation
--no-header Disable auto-generated file header
--no-default-non-nullable Don't treat defaults as non-nullable
--no-add-default-values Don't add default values from OpenAPI to properties
--mutable-arrays Use List<T> instead of IReadOnlyList<T>
--mutable-dictionaries Use Dictionary<K,V> instead of IReadOnlyDictionary<K,V>
--omit-json-attributes Skip [JsonPropertyName] on generated properties
--inline-type-aliases Inline primitive aliases instead of emitting wrapper types
--no-validation-attributes Skip validation attributes from OpenAPI constraints
--no-deprecated-attributes Skip [Obsolete] on deprecated schemas and properties
-v, --version Show version information
-h, --help Show this help message
You can also reference the core library directly for programmatic code generation:
using OpenApiCodeGenerator;
var generator = new CSharpSchemaGenerator(new GeneratorOptions
{
Namespace = "MyApp.Models",
ModelPrefix = "Api",
IncludeSchemas = ["User", "Address"],
GenerateDocComments = true
});
string code = generator.GenerateFromFile("petstore.yaml");
File.WriteAllText("Models.cs", code);Given a simple Petstore OpenAPI spec, the generator produces:
// <auto-generated>
// This file was auto-generated by OpenApiCodeGenerator.
// Do not make direct changes to the file.
// </auto-generated>
#nullable enable
using System.Text.Json.Serialization;
namespace Generated.Petstore;
/// <summary>
/// Order Status
/// </summary>
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum OrderStatus
{
[JsonStringEnumMemberName("placed")]
Placed,
[JsonStringEnumMemberName("approved")]
Approved,
[JsonStringEnumMemberName("delivered")]
Delivered
}
/// <summary>
/// pet status in the store
/// </summary>
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum PetStatus
{
[JsonStringEnumMemberName("available")]
Available,
[JsonStringEnumMemberName("pending")]
Pending,
[JsonStringEnumMemberName("sold")]
Sold
}
public record Order
{
[JsonPropertyName("id")]
public long? Id { get; init; }
[JsonPropertyName("petId")]
public long? PetId { get; init; }
[JsonPropertyName("quantity")]
public int? Quantity { get; init; }
[JsonPropertyName("shipDate")]
public DateTimeOffset? ShipDate { get; init; }
/// <summary>
/// Order Status
/// </summary>
[JsonPropertyName("status")]
public OrderStatus? Status { get; init; }
[JsonPropertyName("complete")]
public bool? Complete { get; init; }
}
public record Category
{
[JsonPropertyName("id")]
public long? Id { get; init; }
[JsonPropertyName("name")]
public string? Name { get; init; }
}
public record User
{
[JsonPropertyName("id")]
public long? Id { get; init; }
[JsonPropertyName("username")]
public string? Username { get; init; }
[JsonPropertyName("firstName")]
public string? FirstName { get; init; }
[JsonPropertyName("lastName")]
public string? LastName { get; init; }
[JsonPropertyName("email")]
public string? Email { get; init; }
[JsonPropertyName("password")]
public string? Password { get; init; }
[JsonPropertyName("phone")]
public string? Phone { get; init; }
/// <summary>
/// User Status
/// </summary>
[JsonPropertyName("userStatus")]
public int? UserStatus { get; init; }
}
public record Tag
{
[JsonPropertyName("id")]
public long? Id { get; init; }
[JsonPropertyName("name")]
public string? Name { get; init; }
}
public record Pet
{
[JsonPropertyName("id")]
public long? Id { get; init; }
[JsonPropertyName("name")]
public required string Name { get; init; }
[JsonPropertyName("category")]
public Category? Category { get; init; }
[JsonPropertyName("photoUrls")]
public required IReadOnlyList<string> PhotoUrls { get; init; }
[JsonPropertyName("tags")]
public IReadOnlyList<Tag>? Tags { get; init; }
/// <summary>
/// pet status in the store
/// </summary>
[JsonPropertyName("status")]
public PetStatus? Status { get; init; }
}
public record ApiResponse
{
[JsonPropertyName("code")]
public int? Code { get; init; }
[JsonPropertyName("type")]
public string? Type { get; init; }
[JsonPropertyName("message")]
public string? Message { get; init; }
}| Option | Default | Description |
|---|---|---|
Namespace |
GeneratedModels |
C# namespace for generated types |
ModelPrefix |
null |
Prefix every generated model type name |
GenerateDocComments |
true |
Include XML doc comments from OpenAPI descriptions |
GenerateFileHeader |
true |
Include auto-generated file header |
DefaultNonNullable |
true |
Treat properties with defaults as non-nullable |
UseImmutableArrays |
true |
Use IReadOnlyList<T> for arrays |
UseImmutableDictionaries |
true |
Use IReadOnlyDictionary<string, T> for maps |
AddDefaultValuesToProperties |
true |
Add default values from OpenAPI to generated properties |
IncludeSchemas |
null |
Generate only the named schemas and their dependencies |
OmitJsonPropertyNameAttributes |
false |
Skip [JsonPropertyName] on generated properties |
InlinePrimitiveTypeAliases |
false |
Inline primitive aliases instead of emitting wrapper types |
EmitValidationAttributes |
true |
Emit validation attributes ([Range], [StringLength], etc.) from OpenAPI constraints |
EmitObsoleteAttribute |
true |
Emit [Obsolete] on deprecated schemas and properties |
The CLI is Native AOT compatible. Publish a fast-starting, self-contained native executable with:
dotnet publish src/OpenApiCodeGenerator.Cli -c Release -r <RID>Replace <RID> with your target runtime ID, e.g. win-x64, linux-x64, or osx-arm64. Native AOT publishing requires the platform toolchain described in the Native AOT prerequisites. The CI pipeline verifies AOT compatibility on every build.
Please see CONTRIBUTING.md for guidelines.
See the LICENSE file for details.