-
Notifications
You must be signed in to change notification settings - Fork 11
Description
Summary
Add an option to s2cs (JSON Structure to C#) and a2cs (Avro to C#) commands that generates C# models compatible with OpenAPI Generator's output style.
Motivation
When integrating Avrotize-generated models with OpenAPI Generator-produced API clients, there's a structural mismatch:
| Aspect | OpenAPI Generator | Avrotize (current) |
|---|---|---|
| Property style | Option<T> wrapper with dual accessors |
Simple auto-properties |
| Null tracking | Explicit Option<T>.IsSet for not-set vs null |
Standard nullable types |
| JSON serialization | Custom JsonConverter<T> with manual Read/Write |
Attribute-based ([JsonPropertyName]) |
| Validation | IValidatableObject interface |
None |
This makes it difficult to use Avrotize as a drop-in replacement for OpenAPI Generator's model generation while still using OpenAPI Generator for API client scaffolding.
Proposed Solution
Add a new flag to both commands:
avrotize s2cs schema.struct.json --out ./models --openapi-generator-compat
avrotize a2cs schema.avsc --out ./models --openapi-generator-compatWhen enabled, the generated C# classes would include:
-
Option<T>wrapper pattern for optional properties with dual accessors:public Option<string?> BitlyUrlOption { get; private set; } public string? BitlyUrl { get => BitlyUrlOption; set => BitlyUrlOption = new(value); }
-
Custom JSON converter per class for fine-grained serialization control
-
IValidatableObjectimplementation (can be empty initially) -
Constructor accepting all properties as
Option<T>parameters
Example Comparison
Current Avrotize output (284 lines for Gif.cs):
public partial class Gif
{
[JsonPropertyName("bitly_url")]
public string? BitlyUrl { get; set; }
// ...
}With --openapi-generator-compat (matching OpenAPI Generator's 815 lines):
public partial class Gif : IValidatableObject
{
[JsonIgnore]
public Option<string?> BitlyUrlOption { get; private set; }
[JsonPropertyName("bitly_url")]
public string? BitlyUrl { get => BitlyUrlOption; set => BitlyUrlOption = new(value); }
// ...
}
public class GifJsonConverter : JsonConverter<Gif> { /* ... */ }Benefits
- Enables using Avrotize for model generation while using OpenAPI Generator for API client scaffolding
- Preserves three-way null semantics (not-set vs explicitly-null vs value)
- Provides seamless interoperability without runtime mapping overhead
Additional Context
This came from investigating how to integrate oas2s (OpenAPI to JSON Structure) output with OpenAPI Generator's C# client. See analysis in PR #151.