Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f5f894b
Introduce --integer-type CLI argument
christianhelle Oct 18, 2025
0ca6570
Add IntegerType property to CodeGeneratorSettings
christianhelle Oct 18, 2025
bf52800
Enable IntegerType setting in GenerateCommand
christianhelle Oct 18, 2025
dc53d89
Add custom integer type processing in CSharpClientGeneratorFactory
christianhelle Oct 18, 2025
deeaf2b
Add tests for integer type generation with and without format
christianhelle Oct 18, 2025
cc253ea
Update README to document --integer-type option for OpenAPI integer t…
christianhelle Oct 18, 2025
a1a3b8e
Add `integerType` property to JSON Schema definition
christianhelle Oct 18, 2025
e0a61e6
Document usage of `--integer-type` CLI argument in NuGet README
christianhelle Oct 18, 2025
e3b29eb
Update MSBuild README
christianhelle Oct 18, 2025
59c3b86
Update source generator README
christianhelle Oct 18, 2025
0f373e1
Update refitter-file-format docfx article
christianhelle Oct 18, 2025
8198259
Update cli tool docfx article
christianhelle Oct 18, 2025
0f8685c
Rename test class to `IntegerFormatTests` for consistency
christianhelle Oct 18, 2025
50662f3
Introduce `IntegerType` enum for OpenAPI integer type handling
christianhelle Oct 19, 2025
a4741d7
Add enum constraint to `integerType` in JSON Schema and update descri…
christianhelle Oct 19, 2025
4d4957c
Update documentation to reflect `integerType` default as `Int32` and …
christianhelle Oct 19, 2025
364fad4
Document `--integer-type` CLI argument in Copilot instructions
christianhelle Oct 19, 2025
cbcdbd8
Combine the collections into a single array/list before iteration to …
christianhelle Oct 19, 2025
5feb7c1
Extend `IntegerFormatTests` to cover integer formats in request param…
christianhelle Oct 20, 2025
2b3eac5
Extend `IntegerFormatTests` to include complex object and schema comb…
christianhelle Oct 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ dotnet run --project src/Refitter --configuration Release --framework net9.0 --
- `--disposable`: Generate IDisposable clients
- `--collection-format`: Control query parameter collection formatting (Multi/Csv/Ssv/Tsv/Pipes)
- `--no-banner`: Hide donation banner in CLI output
- `--integer-type`: Set the .NET type for OpenAPI integers without a format specifier (Int32/Int64)

### Working with OpenAPI Specifications
- Test resources are located in `src/Refitter.Tests/Resources/V2/` and `src/Refitter.Tests/Resources/V3/`
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ OPTIONS:
See https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism for more information
--disposable Generate refit clients that implement IDisposable
--no-inline-json-converters Don't inline JsonConverter attributes for enum properties. When disabled, enum properties will not have [JsonConverter(typeof(JsonStringEnumConverter))] attributes
--integer-type int The .NET type to use for OpenAPI integer types without a format specifier. Common values: 'int' (default), 'long'
```

To generate code from an OpenAPI specifications file, run the following:
Expand Down Expand Up @@ -291,6 +292,7 @@ The following is an example `.refitter` file
"dictionaryInstanceType": "System.Collections.Generic.Dictionary",
"arrayBaseType": "System.Collections.ObjectModel.Collection",
"dictionaryBaseType": "System.Collections.Generic.Dictionary",
"integerType": "Int32", // Optional. Default="Int32". The .NET type for OpenAPI integers without a format. Possible values: "Int32", "Int64"
"propertySetterAccessModifier": "",
"generateImmutableArrayProperties": false,
"generateImmutableDictionaryProperties": false,
Expand Down Expand Up @@ -378,6 +380,7 @@ The following is an example `.refitter` file
- `dictionaryInstanceType` - Default is `System.Collections.Generic.Dictionary`,
- `arrayBaseType` - Default is `System.Collections.ObjectModel.Collection`,
- `dictionaryBaseType` - Default is `System.Collections.Generic.Dictionary`,
- `integerType` - Default is `Int32`. The .NET type to use for OpenAPI integer types without a format specifier. Possible values: `Int32`, `Int64`
- `propertySetterAccessModifier` - Default is ``,
- `generateImmutableArrayProperties` - Default is false,
- `generateImmutableDictionaryProperties` - Default is false,
Expand Down
2 changes: 2 additions & 0 deletions docs/docfx_project/articles/cli-tool.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ EXAMPLES:
refitter ./openapi.json --collection-format Csv
refitter ./openapi.json --simple-output
refitter ./openapi.json --no-inline-json-converters
refitter ./openapi.json --integer-type long

ARGUMENTS:
[URL or input file] URL or file path to OpenAPI Specification file
Expand Down Expand Up @@ -118,6 +119,7 @@ OPTIONS:
See https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism for more information
--disposable Generate refit clients that implement IDisposable
--no-inline-json-converters Don't inline JsonConverter attributes for enum properties. When disabled, enum properties will not have [JsonConverter(typeof(JsonStringEnumConverter))] attributes
--integer-type int The .NET type to use for OpenAPI integer types without a format specifier. Common values: 'int' (default), 'long'
```

## CLI Tool Output Example
Expand Down
2 changes: 2 additions & 0 deletions docs/docfx_project/articles/refitter-file-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ The following is an example `.refitter` file
"dictionaryInstanceType": "System.Collections.Generic.Dictionary",
"arrayBaseType": "System.Collections.ObjectModel.Collection",
"dictionaryBaseType": "System.Collections.Generic.Dictionary",
"integerType": "Int32", // Optional. Default="Int32". The .NET type for OpenAPI integers without a format. Possible values: "Int32", "Int64"
"propertySetterAccessModifier": "",
"generateImmutableArrayProperties": false,
"generateImmutableDictionaryProperties": false,
Expand Down Expand Up @@ -192,6 +193,7 @@ The following is an example `.refitter` file
- `dictionaryInstanceType` - Default is `System.Collections.Generic.Dictionary`,
- `arrayBaseType` - Default is `System.Collections.ObjectModel.Collection`,
- `dictionaryBaseType` - Default is `System.Collections.Generic.Dictionary`,
- `integerType` - Default is `Int32`. The .NET type to use for OpenAPI integer types without a format specifier. Possible values: `Int32`, `Int64`
- `propertySetterAccessModifier` - Default is ``,
- `generateImmutableArrayProperties` - Default is false,
- `generateImmutableDictionaryProperties` - Default is false,
Expand Down
5 changes: 5 additions & 0 deletions docs/json-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@
"description": "Gets or sets the generic dictionary .NET type which is used as base class (default: 'Dictionary').",
"type": "string"
},
"integerType": {
"description": "Gets or sets the .NET type for OpenAPI integers without a format specifier (default: Int32). Possible values: Int32, Int64.",
"type": "string",
"enum": ["Int32", "Int64"]
},
"propertySetterAccessModifier": {
"description": "Gets the access modifier of property setters (default: '').",
"type": "string"
Expand Down
94 changes: 94 additions & 0 deletions src/Refitter.Core/CSharpClientGeneratorFactory.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Reflection;
using NJsonSchema;
using NJsonSchema.CodeGeneration;
using NJsonSchema.CodeGeneration.CSharp;
using NSwag;
Expand All @@ -18,6 +19,8 @@ public CustomCSharpClientGenerator Create()
}
}

ApplyCustomIntegerType();

var csharpClientGeneratorSettings = new CSharpClientGeneratorSettings
{
GenerateClientClasses = false,
Expand Down Expand Up @@ -60,6 +63,97 @@ public CustomCSharpClientGenerator Create()
return generator;
}

private void ApplyCustomIntegerType()
{
var customIntegerType = settings.CodeGeneratorSettings?.IntegerType ?? IntegerType.Int32;
if (customIntegerType == IntegerType.Int32)
return;
Comment thread
christianhelle marked this conversation as resolved.

ProcessSchemasForIntegerType(document.Components.Schemas);

foreach (var path in document.Paths)
{
foreach (var operation in path.Value.Values)
{
if (operation == null) continue;

foreach (var parameter in operation.Parameters)
{
if (parameter.ActualSchema.Type == JsonObjectType.Integer &&
string.IsNullOrEmpty(parameter.ActualSchema.Format))
{
parameter.ActualSchema.Format = "int64";
}
}

if (operation.RequestBody?.Content != null)
{
foreach (var content in operation.RequestBody.Content.Values)
{
ProcessSchemaForIntegerType(content.Schema);
}
}

foreach (var response in operation.Responses.Values)
{
if (response.Content != null)
{
foreach (var content in response.Content.Values)
{
ProcessSchemaForIntegerType(content.Schema);
}
}
}
}
}
}

private void ProcessSchemasForIntegerType(IDictionary<string, JsonSchema> schemas)
{
foreach (var schema in schemas.Values)
{
ProcessSchemaForIntegerType(schema);
}
}

private void ProcessSchemaForIntegerType(JsonSchema? schema)
{
if (schema == null) return;

var actualSchema = schema.ActualSchema;

if (actualSchema.Type == JsonObjectType.Integer &&
string.IsNullOrEmpty(actualSchema.Format))
{
actualSchema.Format = "int64";
}

foreach (var property in actualSchema.Properties.Values)
{
ProcessSchemaForIntegerType(property);
}

if (actualSchema.Item != null)
{
ProcessSchemaForIntegerType(actualSchema.Item);
}

if (actualSchema.AdditionalPropertiesSchema != null)
{
ProcessSchemaForIntegerType(actualSchema.AdditionalPropertiesSchema);
}

var subSchemas = actualSchema.AllOf
.Concat(actualSchema.OneOf)
.Concat(actualSchema.AnyOf)
.ToArray();

foreach (var subSchema in subSchemas)
{
ProcessSchemaForIntegerType(subSchema);
}
}

private static void MapCSharpGeneratorSettings(
CodeGeneratorSettings? source,
CSharpGeneratorSettings destination)
Expand Down
18 changes: 18 additions & 0 deletions src/Refitter.Core/IntegerType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace Refitter.Core;

/// <summary>
/// Specifies the .NET type to use for OpenAPI integer types
/// without a format specifier
/// </summary>
public enum IntegerType
{
/// <summary>
/// Use System.Int32 (int) for integers without format
/// </summary>
Int32,

/// <summary>
/// Use System.Int64 (long) for integers without format
/// </summary>
Int64
}
6 changes: 6 additions & 0 deletions src/Refitter.Core/Settings/CodeGeneratorSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ Gets or sets a value indicating whether a required property must be defined in J
[Description("Gets or sets the time span .NET type (default: 'TimeSpan').")]
public string TimeSpanType { get; set; } = "System.TimeSpan";

/// <summary>
/// Gets or sets the .NET type for OpenAPI integers without a format specifier (default: Int32).
/// </summary>
[Description("Gets or sets the .NET type for OpenAPI integers without a format specifier (default: Int32).")]
public IntegerType IntegerType { get; set; } = IntegerType.Int32;

/// <summary>
/// Gets or sets the generic array .NET type (default: 'ICollection').
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Refitter.MSBuild/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ The following is an example `.refitter` file
"dictionaryInstanceType": "System.Collections.Generic.Dictionary",
"arrayBaseType": "System.Collections.ObjectModel.Collection",
"dictionaryBaseType": "System.Collections.Generic.Dictionary",
"integerType": "Int32", // Optional. Default="Int32". The .NET type for OpenAPI integers without a format. Possible values: "Int32", "Int64"
"propertySetterAccessModifier": "",
"generateImmutableArrayProperties": false,
"generateImmutableDictionaryProperties": false,
Expand Down Expand Up @@ -181,6 +182,7 @@ The following is an example `.refitter` file
- `dictionaryInstanceType` - Default is `System.Collections.Generic.Dictionary`,
- `arrayBaseType` - Default is `System.Collections.ObjectModel.Collection`,
- `dictionaryBaseType` - Default is `System.Collections.Generic.Dictionary`,
- `integerType` - Default is `Int32`. The .NET type to use for OpenAPI integer types without a format specifier. Possible values: `Int32`, `Int64`
- `propertySetterAccessModifier` - Default is ``,
- `generateImmutableArrayProperties` - Default is false,
- `generateImmutableDictionaryProperties` - Default is false,
Expand Down
2 changes: 2 additions & 0 deletions src/Refitter.SourceGenerator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ The following is an example `.refitter` file
"dictionaryInstanceType": "System.Collections.Generic.Dictionary",
"arrayBaseType": "System.Collections.ObjectModel.Collection",
"dictionaryBaseType": "System.Collections.Generic.Dictionary",
"integerType": "int", // Optional. Default="int". The .NET type for OpenAPI integers without a format. Common values: "int", "long"
"propertySetterAccessModifier": "",
"generateImmutableArrayProperties": false,
"generateImmutableDictionaryProperties": false,
Expand Down Expand Up @@ -179,6 +180,7 @@ The following is an example `.refitter` file
- `dictionaryInstanceType` - Default is `System.Collections.Generic.Dictionary`,
- `arrayBaseType` - Default is `System.Collections.ObjectModel.Collection`,
- `dictionaryBaseType` - Default is `System.Collections.Generic.Dictionary`,
- `integerType` - Default is `int`. The .NET type to use for OpenAPI integer types without a format specifier. Common values: `int`, `long`
- `propertySetterAccessModifier` - Default is ``,
- `generateImmutableArrayProperties` - Default is false,
- `generateImmutableDictionaryProperties` - Default is false,
Expand Down
Loading
Loading