Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -458,10 +458,13 @@ public CodegenModel fromModel(String name, Schema schema) {
name = normalizeSchemaName(name);
CodegenModel mdl = super.fromModel(name, schema);

// Detect integer enums - check both the schema type and the dataType
// Detect numeric enums - check both the schema type and the dataType
// Note: "number" type in OpenAPI can include integer values in enums
if (mdl.isEnum) {
String schemaType = schema != null ? schema.getType() : null;
if ("integer".equals(schemaType) || "int".equals(mdl.dataType) || "int64".equals(mdl.dataType)) {
if ("integer".equals(schemaType) || "number".equals(schemaType) ||
"int".equals(mdl.dataType) || "int64".equals(mdl.dataType) ||
"float".equals(mdl.dataType) || "float64".equals(mdl.dataType)) {
mdl.vendorExtensions.put("x-is-integer-enum", true);
}
}
Expand Down Expand Up @@ -606,22 +609,38 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
return objs;
}

/**
* Resolve a schema reference to its target schema.
* This is needed to properly detect nested maps/arrays when the schema is a $ref.
*/
private Schema resolveSchema(Schema schema) {
if (schema != null && schema.get$ref() != null) {
Schema resolved = ModelUtils.getReferencedSchema(this.openAPI, schema);
return resolved != null ? resolved : schema;
}
return schema;
}

@Override
public String getTypeDeclaration(Schema p) {
if (ModelUtils.isArraySchema(p)) {
Schema inner = ModelUtils.getSchemaItems(p);
// Resolve the schema to check for nested maps/arrays - refs that point to map/array schemas
Schema resolved = resolveSchema(p);

if (ModelUtils.isArraySchema(resolved)) {
Schema inner = ModelUtils.getSchemaItems(resolved);
if (inner == null) {
return null;
}
return "seq[" + getTypeDeclaration(inner) + "]";
} else if (ModelUtils.isMapSchema(p)) {
Schema inner = ModelUtils.getAdditionalProperties(p);
} else if (ModelUtils.isMapSchema(resolved)) {
Schema inner = ModelUtils.getAdditionalProperties(resolved);
if (inner == null) {
inner = new StringSchema();
}
return "Table[string, " + getTypeDeclaration(inner) + "]";
}

// For non-containers, use the original schema to preserve model names
String schemaType = getSchemaType(p);
if (typeMapping.containsKey(schemaType)) {
return typeMapping.get(schemaType);
Expand Down Expand Up @@ -719,10 +738,17 @@ private String sanitizeNimIdentifier(String name) {

@Override
public String toEnumVarName(String name, String datatype) {
// Handle negative numbers by prefixing with "Neg" to avoid collisions
// e.g., -1 and 1 would both become `1` without this, causing invalid syntax
if (name.startsWith("-")) {
name = "Neg" + name.substring(1);
}

name = name.replace(" ", "_");
name = StringUtils.camelize(name);

// starts with number or contains any character not allowed,see
// starts with number or contains any character not allowed, see
// https://nim-lang.org/docs/manual.html#lexical-analysis-identifiers-amp-keywords
if (isValidIdentifier(name)) {
return name;
} else {
Expand Down
26 changes: 26 additions & 0 deletions modules/openapi-generator/src/test/resources/3_0/nim/petstore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1020,3 +1020,29 @@ components:
type: array
items:
$ref: '#/components/schemas/PetReview'

# Test numeric enum with negative values
DigestEmailFrequency:
description: Email digest frequency with negative value for disabled
type: number
enum: [-1, 0, 1, 2]

# Test nested maps (map of maps)
StringMap:
description: A simple string to string map
type: object
additionalProperties:
type: string
NestedStringMap:
description: A nested map (string to map of string to string)
type: object
additionalProperties:
$ref: '#/components/schemas/StringMap'
PetStatistics:
description: Statistics about a pet including nested map for health records
type: object
properties:
groomingHistory:
$ref: '#/components/schemas/StringMap'
healthRecords:
$ref: '#/components/schemas/NestedStringMap'
2 changes: 2 additions & 0 deletions samples/client/petstore/nim/.openapi-generator/FILES
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ petstore/apis/api_user.nim
petstore/models/model_any_type.nim
petstore/models/model_api_response.nim
petstore/models/model_category.nim
petstore/models/model_digest_email_frequency.nim
petstore/models/model_get_pet_reviews200response.nim
petstore/models/model_get_pet_reviews_response_with_presence.nim
petstore/models/model_get_pet_stats200response.nim
Expand All @@ -23,6 +24,7 @@ petstore/models/model_pet_positions.nim
petstore/models/model_pet_priority.nim
petstore/models/model_pet_review.nim
petstore/models/model_pet_reviews_response.nim
petstore/models/model_pet_statistics.nim
petstore/models/model_record_string_before_string_or_null_after_string_or_null_value.nim
petstore/models/model_tag.nim
petstore/models/model_unfavorite_pet_request.nim
Expand Down
4 changes: 4 additions & 0 deletions samples/client/petstore/nim/petstore.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# Models
import petstore/models/model_api_response
import petstore/models/model_category
import petstore/models/model_digest_email_frequency
import petstore/models/model_get_pet_reviews200response
import petstore/models/model_get_pet_reviews_response_with_presence
import petstore/models/model_get_pet_stats200response
Expand All @@ -25,13 +26,15 @@ import petstore/models/model_pet_positions
import petstore/models/model_pet_priority
import petstore/models/model_pet_review
import petstore/models/model_pet_reviews_response
import petstore/models/model_pet_statistics
import petstore/models/model_record_string_before_string_or_null_after_string_or_null_value
import petstore/models/model_tag
import petstore/models/model_unfavorite_pet_request
import petstore/models/model_user

export model_api_response
export model_category
export model_digest_email_frequency
export model_get_pet_reviews200response
export model_get_pet_reviews_response_with_presence
export model_get_pet_stats200response
Expand All @@ -47,6 +50,7 @@ export model_pet_positions
export model_pet_priority
export model_pet_review
export model_pet_reviews_response
export model_pet_statistics
export model_record_string_before_string_or_null_after_string_or_null_value
export model_tag
export model_unfavorite_pet_request
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#
# OpenAPI Petstore
#
# This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
# The version of the OpenAPI document: 1.0.0
#
# Generated by: https://openapi-generator.tech
#

import json
import tables
import marshal
import options


type DigestEmailFrequency* {.pure.} = enum
Neg1
`0`
`1`
`2`

func `%`*(v: DigestEmailFrequency): JsonNode =
result = case v:
of DigestEmailFrequency.Neg1: %(-1)
of DigestEmailFrequency.`0`: %(0)
of DigestEmailFrequency.`1`: %(1)
of DigestEmailFrequency.`2`: %(2)

func `$`*(v: DigestEmailFrequency): string =
result = case v:
of DigestEmailFrequency.Neg1: $(-1)
of DigestEmailFrequency.`0`: $(0)
of DigestEmailFrequency.`1`: $(1)
of DigestEmailFrequency.`2`: $(2)
proc to*(node: JsonNode, T: typedesc[DigestEmailFrequency]): DigestEmailFrequency =
if node.kind != JInt:
raise newException(ValueError, "Expected integer for enum DigestEmailFrequency, got " & $node.kind)
let intVal = node.getInt()
case intVal:
of -1:
return DigestEmailFrequency.Neg1
of 0:
return DigestEmailFrequency.`0`
of 1:
return DigestEmailFrequency.`1`
of 2:
return DigestEmailFrequency.`2`
else:
raise newException(ValueError, "Invalid enum value for DigestEmailFrequency: " & $intVal)

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#
# OpenAPI Petstore
#
# This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
# The version of the OpenAPI document: 1.0.0
#
# Generated by: https://openapi-generator.tech
#

import json
import tables
import marshal
import options


type PetStatistics* = object
## Statistics about a pet including nested map for health records
groomingHistory*: Option[Table[string, string]] ## A simple string to string map
healthRecords*: Option[Table[string, Table[string, string]]] ## A nested map (string to map of string to string)

Loading