Skip to content

Commit 44e26b0

Browse files
committed
progress fixing nested map support in cpp generators
1 parent 753330d commit 44e26b0

6 files changed

Lines changed: 160 additions & 50 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppQtAbstractCodegen.java

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,22 @@ public String toModelImport(String name) {
176176
return "#include \"" + folder + name + ".h\"";
177177
}
178178

179+
/**
180+
* Resolve a schema reference. If the schema has a $ref, return the referenced schema.
181+
* This is for nested maps.
182+
*/
183+
private Schema resolveSchema(Schema schema) {
184+
if (schema == null) {
185+
return null;
186+
}
187+
if (StringUtils.isNotEmpty(schema.get$ref())) {
188+
String ref = ModelUtils.getSimpleRef(schema.get$ref());
189+
Schema resolved = ModelUtils.getSchema(openAPI, ref);
190+
return resolved != null ? resolved : schema;
191+
}
192+
return schema;
193+
}
194+
179195
/**
180196
* Optional - type declaration. This is a String which is used by the templates to instantiate your
181197
* types. There is typically special handling for different property types
@@ -185,18 +201,19 @@ public String toModelImport(String name) {
185201
@Override
186202
@SuppressWarnings("rawtypes")
187203
public String getTypeDeclaration(Schema p) {
188-
String openAPIType = getSchemaType(p);
189-
190-
if (ModelUtils.isArraySchema(p)) {
191-
Schema inner = ModelUtils.getSchemaItems(p);
192-
return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
193-
} else if (ModelUtils.isMapSchema(p)) {
194-
Schema inner = ModelUtils.getAdditionalProperties(p);
195-
return getSchemaType(p) + "<QString, " + getTypeDeclaration(inner) + ">";
196-
} else if (ModelUtils.isBinarySchema(p)) {
197-
return getSchemaType(p);
198-
} else if (ModelUtils.isFileSchema(p)) {
199-
return getSchemaType(p);
204+
Schema schema = resolveSchema(p);
205+
String openAPIType = getSchemaType(schema);
206+
207+
if (ModelUtils.isArraySchema(schema)) {
208+
Schema inner = ModelUtils.getSchemaItems(schema);
209+
return getSchemaType(schema) + "<" + getTypeDeclaration(inner) + ">";
210+
} else if (ModelUtils.isMapSchema(schema)) {
211+
Schema inner = ModelUtils.getAdditionalProperties(schema);
212+
return getSchemaType(schema) + "<QString, " + getTypeDeclaration(inner) + ">";
213+
} else if (ModelUtils.isBinarySchema(schema)) {
214+
return getSchemaType(schema);
215+
} else if (ModelUtils.isFileSchema(schema)) {
216+
return getSchemaType(schema);
200217
}
201218
if (foundationClasses.contains(openAPIType)) {
202219
return openAPIType;
@@ -210,29 +227,30 @@ public String getTypeDeclaration(Schema p) {
210227
@Override
211228
@SuppressWarnings("rawtypes")
212229
public String toDefaultValue(Schema p) {
213-
if (ModelUtils.isBooleanSchema(p)) {
230+
Schema schema = resolveSchema(p);
231+
if (ModelUtils.isBooleanSchema(schema)) {
214232
return "false";
215-
} else if (ModelUtils.isDateSchema(p)) {
233+
} else if (ModelUtils.isDateSchema(schema)) {
216234
return "NULL";
217-
} else if (ModelUtils.isDateTimeSchema(p)) {
235+
} else if (ModelUtils.isDateTimeSchema(schema)) {
218236
return "NULL";
219-
} else if (ModelUtils.isNumberSchema(p)) {
220-
if (SchemaTypeUtil.FLOAT_FORMAT.equals(p.getFormat())) {
237+
} else if (ModelUtils.isNumberSchema(schema)) {
238+
if (SchemaTypeUtil.FLOAT_FORMAT.equals(schema.getFormat())) {
221239
return "0.0f";
222240
}
223241
return "0.0";
224-
} else if (ModelUtils.isIntegerSchema(p)) {
225-
if (SchemaTypeUtil.INTEGER64_FORMAT.equals(p.getFormat())) {
242+
} else if (ModelUtils.isIntegerSchema(schema)) {
243+
if (SchemaTypeUtil.INTEGER64_FORMAT.equals(schema.getFormat())) {
226244
return "0L";
227245
}
228246
return "0";
229-
} else if (ModelUtils.isMapSchema(p)) {
230-
Schema inner = ModelUtils.getAdditionalProperties(p);
247+
} else if (ModelUtils.isMapSchema(schema)) {
248+
Schema inner = ModelUtils.getAdditionalProperties(schema);
231249
return "QMap<QString, " + getTypeDeclaration(inner) + ">()";
232-
} else if (ModelUtils.isArraySchema(p)) {
233-
Schema inner = ModelUtils.getSchemaItems(p);
250+
} else if (ModelUtils.isArraySchema(schema)) {
251+
Schema inner = ModelUtils.getSchemaItems(schema);
234252
return "QList<" + getTypeDeclaration(inner) + ">()";
235-
} else if (ModelUtils.isStringSchema(p)) {
253+
} else if (ModelUtils.isStringSchema(schema)) {
236254
return "QString(\"\")";
237255
} else if (!StringUtils.isEmpty(p.get$ref())) {
238256
return toModelName(ModelUtils.getSimpleRef(p.get$ref())) + "()";

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppRestSdkClientCodegen.java

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,22 @@ public String toApiFilename(String name) {
362362
return toApiName(name);
363363
}
364364

365+
/**
366+
* Resolve a schema reference. If the schema has a $ref, return the referenced schema.
367+
* This is for nested maps.
368+
*/
369+
private Schema resolveSchema(Schema schema) {
370+
if (schema == null) {
371+
return null;
372+
}
373+
if (StringUtils.isNotEmpty(schema.get$ref())) {
374+
String ref = ModelUtils.getSimpleRef(schema.get$ref());
375+
Schema resolved = ModelUtils.getSchema(openAPI, ref);
376+
return resolved != null ? resolved : schema;
377+
}
378+
return schema;
379+
}
380+
365381
/**
366382
* Optional - type declaration. This is a String which is used by the
367383
* templates to instantiate your types. There is typically special handling
@@ -372,24 +388,25 @@ public String toApiFilename(String name) {
372388
*/
373389
@Override
374390
public String getTypeDeclaration(Schema p) {
375-
String openAPIType = getSchemaType(p);
376-
377-
if (ModelUtils.isArraySchema(p)) {
378-
Schema inner = ModelUtils.getSchemaItems(p);
379-
return getSchemaType(p) + "<" + getTypeDeclaration(inner) + ">";
380-
} else if (ModelUtils.isMapSchema(p)) {
381-
Schema inner = ModelUtils.getAdditionalProperties(p);
382-
return getSchemaType(p) + "<utility::string_t, " + getTypeDeclaration(inner) + ">";
383-
} else if (ModelUtils.isFileSchema(p) || ModelUtils.isBinarySchema(p)) {
391+
Schema schema = resolveSchema(p);
392+
String openAPIType = getSchemaType(schema);
393+
394+
if (ModelUtils.isArraySchema(schema)) {
395+
Schema inner = ModelUtils.getSchemaItems(schema);
396+
return getSchemaType(schema) + "<" + getTypeDeclaration(inner) + ">";
397+
} else if (ModelUtils.isMapSchema(schema)) {
398+
Schema inner = ModelUtils.getAdditionalProperties(schema);
399+
return getSchemaType(schema) + "<utility::string_t, " + getTypeDeclaration(inner) + ">";
400+
} else if (ModelUtils.isFileSchema(schema) || ModelUtils.isBinarySchema(schema)) {
384401
return "std::shared_ptr<" + openAPIType + ">";
385-
} else if (ModelUtils.isStringSchema(p)
386-
|| ModelUtils.isDateSchema(p) || ModelUtils.isDateTimeSchema(p)
387-
|| ModelUtils.isFileSchema(p) || ModelUtils.isUUIDSchema(p)
402+
} else if (ModelUtils.isStringSchema(schema)
403+
|| ModelUtils.isDateSchema(schema) || ModelUtils.isDateTimeSchema(schema)
404+
|| ModelUtils.isFileSchema(schema) || ModelUtils.isUUIDSchema(schema)
388405
|| languageSpecificPrimitives.contains(openAPIType)) {
389406
return toModelName(openAPIType);
390-
} else if (ModelUtils.isObjectSchema(p)) {
407+
} else if (ModelUtils.isObjectSchema(schema)) {
391408
return "std::shared_ptr<Object>";
392-
} else if(typeMapping.containsKey(super.getSchemaType(p))) {
409+
} else if(typeMapping.containsKey(super.getSchemaType(schema))) {
393410
return openAPIType;
394411
}
395412

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CppTinyClientCodegen.java

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,46 @@ public String getTypeDeclaration(String str) {
208208
return str;
209209
}
210210

211+
/**
212+
* Resolve a schema reference. If the schema has a $ref, return the referenced schema.
213+
* This is for nested maps.
214+
*/
215+
private Schema resolveSchema(Schema schema) {
216+
if (schema == null) {
217+
return null;
218+
}
219+
if (StringUtils.isNotEmpty(schema.get$ref())) {
220+
String ref = ModelUtils.getSimpleRef(schema.get$ref());
221+
Schema resolved = ModelUtils.getSchema(openAPI, ref);
222+
return resolved != null ? resolved : schema;
223+
}
224+
return schema;
225+
}
226+
227+
@Override
228+
public String getTypeDeclaration(Schema p) {
229+
Schema schema = resolveSchema(p);
230+
String openAPIType = getSchemaType(schema);
231+
232+
if (ModelUtils.isArraySchema(schema)) {
233+
Schema inner = ModelUtils.getSchemaItems(schema);
234+
return getSchemaType(schema) + "<" + getTypeDeclaration(inner) + ">";
235+
} else if (ModelUtils.isMapSchema(schema)) {
236+
Schema inner = ModelUtils.getAdditionalProperties(schema);
237+
return getSchemaType(schema) + "<std::string, " + getTypeDeclaration(inner) + ">";
238+
}
239+
240+
if (languageSpecificPrimitives.contains(openAPIType)) {
241+
return toModelName(openAPIType);
242+
} else {
243+
return openAPIType;
244+
}
245+
}
246+
211247
private void makeTypeMappings() {
212248
// Types
213249
String cpp_array_type = "std::list";
250+
String cpp_map_type = "std::map";
214251
typeMapping = new HashMap<>();
215252

216253
typeMapping.put("string", "std::string");
@@ -220,6 +257,7 @@ private void makeTypeMappings() {
220257
typeMapping.put("boolean", "bool");
221258
typeMapping.put("double", "double");
222259
typeMapping.put("array", cpp_array_type);
260+
typeMapping.put("map", cpp_map_type);
223261
typeMapping.put("number", "long");
224262
typeMapping.put("binary", "std::string");
225263
typeMapping.put("password", "std::string");
@@ -296,7 +334,7 @@ public String toModelImport(String name) {
296334
return "#include <string>";
297335
} else if (name.equals("std::list")) {
298336
return "#include <list>";
299-
} else if (name.equals("Map")) {
337+
} else if (name.equals("Map") || name.equals("std::map")) {
300338
return "#include <map>";
301339
}
302340
return "#include \"" + name + ".h\"";

modules/openapi-generator/src/main/resources/cpp-tiny/model-body.mustache

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,14 @@ bourne::json
141141
}
142142

143143
{{#vars}}
144-
{{dataType}}{{#isContainer}}{{#isMap}}<string, string>{{/isMap}}{{^isMap}}<{{#items}}{{dataType}}{{/items}}>{{/isMap}}{{/isContainer}}
144+
{{{dataType}}}
145145
{{classname}}::{{getter}}()
146146
{
147147
return {{name}};
148148
}
149149

150150
void
151-
{{classname}}::{{setter}}({{dataType}} {{#isContainer}}{{#isMap}}<string, string>{{/isMap}}{{^isMap}}<{{#items}}{{dataType}}{{/items}}>{{/isMap}}{{/isContainer}} {{name}})
151+
{{classname}}::{{setter}}({{{dataType}}} {{name}})
152152
{
153153
this->{{name}} = {{name}};
154154
}

modules/openapi-generator/src/main/resources/cpp-tiny/model-header.mustache

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,27 +51,22 @@ public:
5151
{{#vars}}
5252
/*! \brief Get {{{description}}}
5353
*/
54-
{{dataType}}{{#isContainer}}{{#isMap}}<std::string, std::string>{{/isMap}}{{^isMap}}<{{#items}}{{dataType}}{{/items}}>{{/isMap}}{{/isContainer}} {{getter}}();
54+
{{{dataType}}} {{getter}}();
5555

5656
/*! \brief Set {{{description}}}
5757
*/
58-
void {{setter}}({{dataType}} {{#isContainer}}{{#isMap}}<std::string, std::string>{{/isMap}}{{^isMap}}<{{#items}}{{dataType}}{{/items}}>{{/isMap}}{{/isContainer}} {{name}});
58+
void {{setter}}({{{dataType}}} {{name}});
5959
{{/vars}}
6060

6161

6262
private:
6363
{{#vars}}
64-
{{^isContainer}}
6564
{{#isPrimitiveType}}
66-
{{dataType}} {{name}}{};
65+
{{{dataType}}} {{name}}{};
6766
{{/isPrimitiveType}}
6867
{{^isPrimitiveType}}
69-
{{dataType}} {{name}};
68+
{{{dataType}}} {{name}};
7069
{{/isPrimitiveType}}
71-
{{/isContainer}}
72-
{{#isContainer}}
73-
{{dataType}}{{#isMap}}<std::string, std::string>{{/isMap}}{{^isMap}}<{{#items}}{{dataType}}{{/items}}>{{/isMap}} {{name}};
74-
{{/isContainer}}
7570
{{/vars}}
7671
};
7772
{{/model}}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
openapi: "3.0.0"
2+
info:
3+
title: Nested Maps Test
4+
description: Test case for nested map types (Record<string, Record<string, string>>)
5+
version: "1.0.0"
6+
paths:
7+
/test:
8+
get:
9+
summary: Test endpoint with nested maps
10+
operationId: getNestedMaps
11+
responses:
12+
"200":
13+
description: OK
14+
content:
15+
application/json:
16+
schema:
17+
$ref: '#/components/schemas/TestModel'
18+
19+
components:
20+
schemas:
21+
# Inner map: Record<string, string>
22+
Record_string.string_:
23+
type: object
24+
additionalProperties:
25+
type: string
26+
27+
# Outer map: Record<string, Record<string, string>>
28+
Record_string.Record_string.string__:
29+
type: object
30+
additionalProperties:
31+
$ref: "#/components/schemas/Record_string.string_"
32+
33+
# Model that uses the nested map
34+
TestModel:
35+
type: object
36+
properties:
37+
id:
38+
type: string
39+
simpleMap:
40+
$ref: "#/components/schemas/Record_string.string_"
41+
nestedMap:
42+
$ref: "#/components/schemas/Record_string.Record_string.string__"

0 commit comments

Comments
 (0)