Schema Type Mapping
OpenApiWeaver maps OpenAPI 3.0-3.2 schema types to C# types as follows.
Primitive types
| OpenAPI Type | OpenAPI Format | C# Type |
|---|---|---|
integer | - | int |
integer | int64 | long |
number | - | decimal |
number | float | float |
number | double | double |
number | decimal | decimal |
boolean | - | bool |
string | - | string |
string | date | DateOnly |
string | date-time | DateTimeOffset |
string | uuid | Guid |
string | binary | byte[] |
Collection types
| OpenAPI Schema | C# Type |
|---|---|
array with items | IReadOnlyList<T> |
object with additionalProperties | IReadOnlyDictionary<string, T> |
object with patternProperties | IReadOnlyDictionary<string, T> |
When a top-level component schema defines additionalProperties or patternProperties, the generated class extends Dictionary<string, T> so that it can hold both declared properties and arbitrary key-value pairs:
Metadata:
type: object
additionalProperties:
type: string
properties:
version:
type: stringpublic sealed class Metadata : Dictionary<string, string>
{
[JsonPropertyName("version")]
public string? Version { get; init; }
}If additionalProperties and patternProperties produce incompatible value types, the generated type falls back to Dictionary<string, JsonElement>.
Object schemas
Object schemas defined in components/schemas are generated as sealed class types. Each property gets a [JsonPropertyName] attribute preserving the original JSON name, while the C# property name is converted to PascalCase:
# OpenAPI schema
Pet:
type: object
required: [id, name]
properties:
id:
type: integer
format: int64
pet_name:
type: string// Generated C#
public sealed class Pet
{
[JsonPropertyName("id")]
public required long Id { get; init; }
[JsonPropertyName("pet_name")]
public required string PetName { get; init; }
}Required properties use the required modifier, while optional nullable properties are annotated with [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]:
public sealed class Pet
{
[JsonPropertyName("id")]
public required long Id { get; init; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("tag")]
public string? Tag { get; init; }
}Inline schemas
Inline object or enum schemas defined inside property definitions, array items, or additionalProperties are generated as nested types under the owning model class, keeping the type hierarchy compact:
Order:
type: object
properties:
status:
type: string
enum: [placed, approved, delivered]public sealed class Order
{
[JsonPropertyName("status")]
public Order.StatusEnum? Status { get; init; }
public readonly record struct StatusEnum(string Value) { ... }
}Composition keywords
| OpenAPI Keyword | C# Mapping |
|---|---|
allOf | Flattened into a single class containing all properties |
oneOf / anyOf | Union-style nullable properties or nullable CLR primitives when the union is a primitive plus null |
Nullable type arrays (OpenAPI 3.2)
OpenAPI 3.2 allows type to be expressed as an array. When one of the entries is null, OpenApiWeaver maps the schema to a nullable CLR type.
partnerResponse:
type: object
properties:
display_name:
type: [string, 'null']
company_id:
type: [integer, 'null']public sealed class PartnerResponse
{
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("display_name")]
public string? DisplayName { get; init; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("company_id")]
public int? CompanyId { get; init; }
}Enums
String enums
OpenAPI string enum values are generated as readonly record struct types with static members. This approach provides type safety and IntelliSense without the limitations of C# enum (which only supports numeric values):
# OpenAPI schema
Status:
type: string
enum: [active, inactive, pending]// Generated C#
[JsonConverter(typeof(StatusJsonConverter))]
public readonly record struct Status(string Value)
{
public static readonly Status Active = new("active");
public static readonly Status Inactive = new("inactive");
public static readonly Status Pending = new("pending");
public override string ToString() => Value;
}
public sealed class StatusJsonConverter : JsonConverter<Status>
{
public override Status Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return new Status(reader.GetString()!);
}
public override void Write(Utf8JsonWriter writer, Status value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.Value);
}
}A dedicated JsonConverter is generated for each string enum to handle serialization and deserialization correctly.
Integer enums
When the OpenAPI schema specifies type: integer with enum, a standard C# enum is generated instead:
# OpenAPI schema
Priority:
type: integer
enum: [0, 1, 2]// Generated C#
public enum Priority
{
Value0 = 0,
Value1 = 1,
Value2 = 2
}When the schema specifies format: int64, the generated enum uses long as the underlying type:
public enum Priority : long
{
Value0 = 0,
Value1 = 1,
Value2 = 2
}Naming conventions
All schema names are converted from their original casing to C# idiomatic conventions:
| Source Convention | C# Convention | Example |
|---|---|---|
snake_case | PascalCase | pet_name -> PetName |
kebab-case | PascalCase | pet-name -> PetName |
camelCase | PascalCase | petName -> PetName |
The original names are always preserved in [JsonPropertyName] attributes to ensure correct serialization.