Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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 @@ -176,6 +176,22 @@ public String toModelImport(String name) {
return "#include \"" + folder + name + ".h\"";
}

/**
* Resolve a schema reference. If the schema has a $ref, return the referenced schema.
* This is for nested maps.
*/
private Schema resolveSchema(Schema schema) {
if (schema == null) {
return null;
}
if (StringUtils.isNotEmpty(schema.get$ref())) {
String ref = ModelUtils.getSimpleRef(schema.get$ref());
Schema resolved = ModelUtils.getSchema(openAPI, ref);
return resolved != null ? resolved : schema;
}
return schema;
}

/**
* Optional - type declaration. This is a String which is used by the templates to instantiate your
* types. There is typically special handling for different property types
Expand All @@ -185,15 +201,20 @@ public String toModelImport(String name) {
@Override
@SuppressWarnings("rawtypes")
public String getTypeDeclaration(Schema p) {
String openAPIType = getSchemaType(p);
// Resolve the schema to check for nested maps/arrays - refs that point to map schemas
Schema resolved = resolveSchema(p);

if (ModelUtils.isArraySchema(p)) {
Schema inner = ModelUtils.getSchemaItems(p);
if (ModelUtils.isArraySchema(resolved)) {
Schema inner = ModelUtils.getSchemaItems(resolved);
return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
} else if (ModelUtils.isMapSchema(p)) {
Schema inner = ModelUtils.getAdditionalProperties(p);
} else if (ModelUtils.isMapSchema(resolved)) {
Schema inner = ModelUtils.getAdditionalProperties(resolved);
return getSchemaType(p) + "<QString, " + getTypeDeclaration(inner) + ">";
} else if (ModelUtils.isBinarySchema(p)) {
}

// For non-containers, use the original schema to preserve model names
String openAPIType = getSchemaType(p);
if (ModelUtils.isBinarySchema(p)) {
return getSchemaType(p);
} else if (ModelUtils.isFileSchema(p)) {
return getSchemaType(p);
Expand All @@ -210,29 +231,30 @@ public String getTypeDeclaration(Schema p) {
@Override
@SuppressWarnings("rawtypes")
public String toDefaultValue(Schema p) {
if (ModelUtils.isBooleanSchema(p)) {
Schema schema = resolveSchema(p);
if (ModelUtils.isBooleanSchema(schema)) {
return "false";
} else if (ModelUtils.isDateSchema(p)) {
} else if (ModelUtils.isDateSchema(schema)) {
return "NULL";
} else if (ModelUtils.isDateTimeSchema(p)) {
} else if (ModelUtils.isDateTimeSchema(schema)) {
return "NULL";
} else if (ModelUtils.isNumberSchema(p)) {
if (SchemaTypeUtil.FLOAT_FORMAT.equals(p.getFormat())) {
} else if (ModelUtils.isNumberSchema(schema)) {
if (SchemaTypeUtil.FLOAT_FORMAT.equals(schema.getFormat())) {
return "0.0f";
}
return "0.0";
} else if (ModelUtils.isIntegerSchema(p)) {
if (SchemaTypeUtil.INTEGER64_FORMAT.equals(p.getFormat())) {
} else if (ModelUtils.isIntegerSchema(schema)) {
if (SchemaTypeUtil.INTEGER64_FORMAT.equals(schema.getFormat())) {
return "0L";
}
return "0";
} else if (ModelUtils.isMapSchema(p)) {
Schema inner = ModelUtils.getAdditionalProperties(p);
} else if (ModelUtils.isMapSchema(schema)) {
Schema inner = ModelUtils.getAdditionalProperties(schema);
return "QMap<QString, " + getTypeDeclaration(inner) + ">()";
} else if (ModelUtils.isArraySchema(p)) {
Schema inner = ModelUtils.getSchemaItems(p);
} else if (ModelUtils.isArraySchema(schema)) {
Schema inner = ModelUtils.getSchemaItems(schema);
return "QList<" + getTypeDeclaration(inner) + ">()";
} else if (ModelUtils.isStringSchema(p)) {
} else if (ModelUtils.isStringSchema(schema)) {
return "QString(\"\")";
} else if (!StringUtils.isEmpty(p.get$ref())) {
return toModelName(ModelUtils.getSimpleRef(p.get$ref())) + "()";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,22 @@ public String toApiFilename(String name) {
return toApiName(name);
}

/**
* Resolve a schema reference. If the schema has a $ref, return the referenced schema.
* This is for nested maps.
*/
private Schema resolveSchema(Schema schema) {
if (schema == null) {
return null;
}
if (StringUtils.isNotEmpty(schema.get$ref())) {
String ref = ModelUtils.getSimpleRef(schema.get$ref());
Schema resolved = ModelUtils.getSchema(openAPI, ref);
return resolved != null ? resolved : schema;
}
return schema;
}

/**
* Optional - type declaration. This is a String which is used by the
* templates to instantiate your types. There is typically special handling
Expand All @@ -372,15 +388,20 @@ public String toApiFilename(String name) {
*/
@Override
public String getTypeDeclaration(Schema p) {
String openAPIType = getSchemaType(p);
// Resolve the schema to check for nested maps/arrays - refs that point to map schemas
Schema resolved = resolveSchema(p);

if (ModelUtils.isArraySchema(p)) {
Schema inner = ModelUtils.getSchemaItems(p);
if (ModelUtils.isArraySchema(resolved)) {
Schema inner = ModelUtils.getSchemaItems(resolved);
return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
} else if (ModelUtils.isMapSchema(p)) {
Schema inner = ModelUtils.getAdditionalProperties(p);
} else if (ModelUtils.isMapSchema(resolved)) {
Schema inner = ModelUtils.getAdditionalProperties(resolved);
return getSchemaType(p) + "<utility::string_t, " + getTypeDeclaration(inner) + ">";
} else if (ModelUtils.isFileSchema(p) || ModelUtils.isBinarySchema(p)) {
}

// For non-containers, use the original schema to preserve model names
String openAPIType = getSchemaType(p);
if (ModelUtils.isFileSchema(p) || ModelUtils.isBinarySchema(p)) {
return "std::shared_ptr<" + openAPIType + ">";
} else if (ModelUtils.isStringSchema(p)
|| ModelUtils.isDateSchema(p) || ModelUtils.isDateTimeSchema(p)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,26 @@ public String getTypeDeclaration(String str) {
return str;
}

/**
* Resolve a schema reference. If the schema has a $ref, return the referenced schema.
* This is for nested maps.
*/
private Schema resolveSchema(Schema schema) {
if (schema == null) {
return null;
}
if (StringUtils.isNotEmpty(schema.get$ref())) {
String ref = ModelUtils.getSimpleRef(schema.get$ref());
Schema resolved = ModelUtils.getSchema(openAPI, ref);
return resolved != null ? resolved : schema;
}
return schema;
}

private void makeTypeMappings() {
// Types
String cpp_array_type = "std::list";
String cpp_map_type = "std::map";
Comment thread
winrid marked this conversation as resolved.
Outdated
typeMapping = new HashMap<>();

typeMapping.put("string", "std::string");
Expand All @@ -220,6 +237,7 @@ private void makeTypeMappings() {
typeMapping.put("boolean", "bool");
typeMapping.put("double", "double");
typeMapping.put("array", cpp_array_type);
typeMapping.put("map", cpp_map_type);
typeMapping.put("number", "long");
typeMapping.put("binary", "std::string");
typeMapping.put("password", "std::string");
Expand Down Expand Up @@ -255,6 +273,17 @@ public String toInstantiationType(Schema p) {

@Override
public String getTypeDeclaration(Schema p) {
// Only resolve for nested maps - check if a $ref points to a map schema
Schema resolved = resolveSchema(p);

// Handle nested maps: if a $ref resolves to a map schema, build the nested type
if (ModelUtils.isMapSchema(resolved)) {
Schema inner = ModelUtils.getAdditionalProperties(resolved);
Comment thread
winrid marked this conversation as resolved.
return getSchemaType(p) + "<std::string, " + getTypeDeclaration(inner) + ">";
}

// For everything else (including arrays), use the original behavior
// The templates handle adding array item types themselves
String openAPIType = getSchemaType(p);
if (languageSpecificPrimitives.contains(openAPIType)) {
return toModelName(openAPIType);
Expand Down Expand Up @@ -296,7 +325,7 @@ public String toModelImport(String name) {
return "#include <string>";
} else if (name.equals("std::list")) {
return "#include <list>";
} else if (name.equals("Map")) {
} else if (name.equals("Map") || name.equals("std::map")) {
return "#include <map>";
}
return "#include \"" + name + ".h\"";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,14 @@ bourne::json
}

{{#vars}}
{{dataType}}{{#isContainer}}{{#isMap}}<string, string>{{/isMap}}{{^isMap}}<{{#items}}{{dataType}}{{/items}}>{{/isMap}}{{/isContainer}}
{{#isMap}}{{{dataType}}}{{/isMap}}{{^isMap}}{{dataType}}{{#isArray}}<{{#items}}{{dataType}}{{/items}}>{{/isArray}}{{/isMap}}
{{classname}}::{{getter}}()
{
return {{name}};
}

void
{{classname}}::{{setter}}({{dataType}} {{#isContainer}}{{#isMap}}<string, string>{{/isMap}}{{^isMap}}<{{#items}}{{dataType}}{{/items}}>{{/isMap}}{{/isContainer}} {{name}})
{{classname}}::{{setter}}({{#isMap}}{{{dataType}}}{{/isMap}}{{^isMap}}{{dataType}}{{#isArray}}<{{#items}}{{dataType}}{{/items}}>{{/isArray}}{{/isMap}} {{name}})
{
this->{{name}} = {{name}};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,27 +51,32 @@ public:
{{#vars}}
/*! \brief Get {{{description}}}
*/
{{dataType}}{{#isContainer}}{{#isMap}}<std::string, std::string>{{/isMap}}{{^isMap}}<{{#items}}{{dataType}}{{/items}}>{{/isMap}}{{/isContainer}} {{getter}}();
{{#isMap}}{{{dataType}}}{{/isMap}}{{^isMap}}{{dataType}}{{#isArray}}<{{#items}}{{dataType}}{{/items}}>{{/isArray}}{{/isMap}} {{getter}}();

/*! \brief Set {{{description}}}
*/
void {{setter}}({{dataType}} {{#isContainer}}{{#isMap}}<std::string, std::string>{{/isMap}}{{^isMap}}<{{#items}}{{dataType}}{{/items}}>{{/isMap}}{{/isContainer}} {{name}});
void {{setter}}({{#isMap}}{{{dataType}}}{{/isMap}}{{^isMap}}{{dataType}}{{#isArray}}<{{#items}}{{dataType}}{{/items}}>{{/isArray}}{{/isMap}} {{name}});
{{/vars}}


private:
{{#vars}}
{{^isContainer}}
{{#isMap}}
{{{dataType}}} {{name}};
{{/isMap}}
{{^isMap}}
{{#isArray}}
{{dataType}}<{{#items}}{{dataType}}{{/items}}> {{name}};
{{/isArray}}
{{^isArray}}
{{#isPrimitiveType}}
{{dataType}} {{name}}{};
{{/isPrimitiveType}}
{{^isPrimitiveType}}
{{dataType}} {{name}};
{{/isPrimitiveType}}
{{/isContainer}}
{{#isContainer}}
{{dataType}}{{#isMap}}<std::string, std::string>{{/isMap}}{{^isMap}}<{{#items}}{{dataType}}{{/items}}>{{/isMap}} {{name}};
{{/isContainer}}
{{/isArray}}
{{/isMap}}
{{/vars}}
};
{{/model}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
openapi: "3.0.0"
info:
title: Nested Maps Test
description: Test case for nested map types (Record<string, Record<string, string>>)
version: "1.0.0"
paths:
/test:
get:
summary: Test endpoint with nested maps
operationId: getNestedMaps
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/TestModel'

components:
schemas:
# Inner map: Record<string, string>
Record_string.string_:
type: object
additionalProperties:
type: string

# Outer map: Record<string, Record<string, string>>
Record_string.Record_string.string__:
type: object
additionalProperties:
$ref: "#/components/schemas/Record_string.string_"

# Model that uses the nested map
TestModel:
type: object
properties:
id:
type: string
simpleMap:
$ref: "#/components/schemas/Record_string.string_"
nestedMap:
$ref: "#/components/schemas/Record_string.Record_string.string__"
Original file line number Diff line number Diff line change
Expand Up @@ -876,4 +876,24 @@ components:
format: "uuid"
pattern: "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"
type: "string"

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:
description: Map of date to grooming notes
$ref: '#/components/schemas/StringMap'
healthRecords:
description: Nested map - category to (date to record)
$ref: '#/components/schemas/NestedStringMap'

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ include/CppRestPetstoreClient/model/CreateUserOrPet_request.h
include/CppRestPetstoreClient/model/Order.h
include/CppRestPetstoreClient/model/Page.h
include/CppRestPetstoreClient/model/Pet.h
include/CppRestPetstoreClient/model/PetStatistics.h
include/CppRestPetstoreClient/model/SchemaWithSet.h
include/CppRestPetstoreClient/model/SchemaWithSet_vaccinationBook.h
include/CppRestPetstoreClient/model/Tag.h
Expand All @@ -49,6 +50,7 @@ src/model/CreateUserOrPet_request.cpp
src/model/Order.cpp
src/model/Page.cpp
src/model/Pet.cpp
src/model/PetStatistics.cpp
src/model/SchemaWithSet.cpp
src/model/SchemaWithSet_vaccinationBook.cpp
src/model/Tag.cpp
Expand Down
Loading
Loading