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 type aliases with full nullable reference type support and System.Text.Json serialization out of the box.
- 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)
--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>
-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",
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 |
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 |
AddDefaultValuesToProperties |
true |
Add default values from OpenAPI to generated properties |
UseImmutableArrays |
true |
Use IReadOnlyList<T> for arrays |
UseImmutableDictionaries |
true |
Use IReadOnlyDictionary<string, T> for maps |
Please see CONTRIBUTING.md for guidelines.
See the LICENSE file for details.