diff --git a/docs/generators/typescript-angular.md b/docs/generators/typescript-angular.md index 65a2cf27a67..c4dbe172ea7 100644 --- a/docs/generators/typescript-angular.md +++ b/docs/generators/typescript-angular.md @@ -23,6 +23,7 @@ sidebar_label: typescript-angular |nullSafeAdditionalProps|Set to make additional properties types declare that their indexer may return undefined| |false| |prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false| |providedInRoot|Use this property to provide Injectables in root (it is only valid in angular version greater or equal to 6.0.0).| |false| +|queryParamObjectFormat|The format for query param objects: 'dot', 'json', 'key'.| |dot| |serviceFileSuffix|The suffix of the file of the generated service (service<suffix>.ts).| |.service| |serviceSuffix|The suffix of the generated service.| |Service| |snapshot|When setting this property to true, the version will be suffixed with -SNAPSHOT.yyyyMMddHHmm| |false| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java index 9c87bc94f3f..b9632aee194 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptAngularClientCodegen.java @@ -27,6 +27,8 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.apache.commons.lang3.StringUtils.capitalize; import static org.openapitools.codegen.utils.StringUtils.*; @@ -38,6 +40,8 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode private static String CLASS_NAME_SUFFIX_PATTERN = "^[a-zA-Z0-9]*$"; private static String FILE_NAME_SUFFIX_PATTERN = "^[a-zA-Z0-9.-]*$"; + public static enum QUERY_PARAM_OBJECT_FORMAT_TYPE {dot, json, key}; + private static final String DEFAULT_IMPORT_PREFIX = "./"; public static final String NPM_REPOSITORY = "npmRepository"; @@ -55,6 +59,7 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode public static final String FILE_NAMING = "fileNaming"; public static final String STRING_ENUMS = "stringEnums"; public static final String STRING_ENUMS_DESC = "Generate string enums instead of objects for enum values."; + public static final String QUERY_PARAM_OBJECT_FORMAT = "queryParamObjectFormat"; protected String ngVersion = "9.0.0"; protected String npmRepository = null; @@ -65,6 +70,7 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode protected String modelFileSuffix = ""; protected String fileNaming = "camelCase"; protected Boolean stringEnums = false; + protected QUERY_PARAM_OBJECT_FORMAT_TYPE queryParamObjectFormat = QUERY_PARAM_OBJECT_FORMAT_TYPE.dot; private boolean taggedUnions = false; @@ -107,6 +113,7 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode this.cliOptions.add(new CliOption(MODEL_FILE_SUFFIX, "The suffix of the file of the generated model (model.ts).")); this.cliOptions.add(new CliOption(FILE_NAMING, "Naming convention for the output files: 'camelCase', 'kebab-case'.").defaultValue(this.fileNaming)); this.cliOptions.add(new CliOption(STRING_ENUMS, STRING_ENUMS_DESC).defaultValue(String.valueOf(this.stringEnums))); + this.cliOptions.add(new CliOption(QUERY_PARAM_OBJECT_FORMAT, "The format for query param objects: 'dot', 'json', 'key'.").defaultValue(this.queryParamObjectFormat.name())); } @Override @@ -223,6 +230,13 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode this.setFileNaming(additionalProperties.get(FILE_NAMING).toString()); } + if (additionalProperties.containsKey(QUERY_PARAM_OBJECT_FORMAT)) { + setQueryParamObjectFormat((String) additionalProperties.get(QUERY_PARAM_OBJECT_FORMAT)); + } + additionalProperties.put("isQueryParamObjectFormatDot", getQueryParamObjectFormatDot()); + additionalProperties.put("isQueryParamObjectFormatJson", getQueryParamObjectFormatJson()); + additionalProperties.put("isQueryParamObjectFormatKey", getQueryParamObjectFormatKey()); + } private void addNpmPackageGeneration(SemVer ngVersion) { @@ -303,11 +317,23 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode return stringEnums; } + public boolean getQueryParamObjectFormatDot() { + return QUERY_PARAM_OBJECT_FORMAT_TYPE.dot.equals(queryParamObjectFormat); + } + + public boolean getQueryParamObjectFormatJson() { + return QUERY_PARAM_OBJECT_FORMAT_TYPE.json.equals(queryParamObjectFormat); + } + + public boolean getQueryParamObjectFormatKey() { + return QUERY_PARAM_OBJECT_FORMAT_TYPE.key.equals(queryParamObjectFormat); + } + @Override public boolean isDataTypeFile(final String dataType) { return dataType != null && dataType.equals("Blob"); } - + @Override public String getTypeDeclaration(Schema p) { if (ModelUtils.isFileSchema(p)) { @@ -615,6 +641,24 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode } } + /** + * Set the query param object format. + * + * @param format the query param object format to use + */ + public void setQueryParamObjectFormat(String format) { + try { + queryParamObjectFormat = QUERY_PARAM_OBJECT_FORMAT_TYPE.valueOf(format); + } catch (IllegalArgumentException e) { + String values = Stream.of(QUERY_PARAM_OBJECT_FORMAT_TYPE.values()) + .map(value -> "'" + value.name() + "'") + .collect(Collectors.joining(", ")); + + String msg = String.format(Locale.ROOT, "Invalid query param object format '%s'. Must be one of %s.", format, values); + throw new IllegalArgumentException(msg); + } + } + /** * Set the file naming type. * diff --git a/modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache b/modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache index 872ea6a262f..33087c984bf 100644 --- a/modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache +++ b/modules/openapi-generator/src/main/resources/typescript-angular/api.service.mustache @@ -107,6 +107,10 @@ export class {{classname}} { } if (typeof value === "object") { + {{#isQueryParamObjectFormatJson}} + httpParams = httpParams.append(key, JSON.stringify(value)); + {{/isQueryParamObjectFormatJson}} + {{^isQueryParamObjectFormatJson}} if (Array.isArray(value)) { (value as any[]).forEach( elem => httpParams = this.addToHttpParamsRecursive(httpParams, elem, key)); } else if (value instanceof Date) { @@ -118,8 +122,9 @@ export class {{classname}} { } } else { Object.keys(value).forEach( k => httpParams = this.addToHttpParamsRecursive( - httpParams, value[k], key != null ? `${key}.${k}` : k)); + httpParams, value[k], key != null ? `${key}{{#isQueryParamObjectFormatDot}}.{{/isQueryParamObjectFormatDot}}{{#isQueryParamObjectFormatKey}}[{{/isQueryParamObjectFormatKey}}${k}{{#isQueryParamObjectFormatKey}}]{{/isQueryParamObjectFormatKey}}` : k)); } + {{/isQueryParamObjectFormatJson}} } else if (key != null) { httpParams = httpParams.append(key, value); } else { diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptAngularClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptAngularClientOptionsProvider.java index 7553e379e4f..ca8c7f491e9 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptAngularClientOptionsProvider.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/TypeScriptAngularClientOptionsProvider.java @@ -42,6 +42,7 @@ public class TypeScriptAngularClientOptionsProvider implements OptionsProvider { public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true"; public static final String FILE_NAMING_VALUE = "camelCase"; public static final String API_MODULE_PREFIX = ""; + public static final String QUERY_PARAM_OBJECT_FORMAT_VALUE = "dot"; public static String SERVICE_SUFFIX = "Service"; public static String SERVICE_FILE_SUFFIX = ".service"; public static String MODEL_SUFFIX = ""; @@ -83,6 +84,7 @@ public class TypeScriptAngularClientOptionsProvider implements OptionsProvider { .put(TypeScriptAngularClientCodegen.FILE_NAMING, FILE_NAMING_VALUE) .put(CodegenConstants.LEGACY_DISCRIMINATOR_BEHAVIOR, "true") .put(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT, "true") + .put(TypeScriptAngularClientCodegen.QUERY_PARAM_OBJECT_FORMAT, QUERY_PARAM_OBJECT_FORMAT_VALUE) .build(); } diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientOptionsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientOptionsTest.java index 92aa51c846d..9bc5eafb1bd 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientOptionsTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/typescriptangular/TypeScriptAngularClientOptionsTest.java @@ -45,5 +45,6 @@ public class TypeScriptAngularClientOptionsTest extends AbstractOptionsTest { verify(clientCodegen).setSupportsES6(Boolean.valueOf(TypeScriptAngularClientOptionsProvider.SUPPORTS_ES6_VALUE)); verify(clientCodegen).setStringEnums(Boolean.parseBoolean(TypeScriptAngularClientOptionsProvider.STRING_ENUMS_VALUE)); verify(clientCodegen).setPrependFormOrBodyParameters(Boolean.valueOf(TypeScriptAngularClientOptionsProvider.PREPEND_FORM_OR_BODY_PARAMETERS_VALUE)); + verify(clientCodegen).setQueryParamObjectFormat(TypeScriptAngularClientOptionsProvider.QUERY_PARAM_OBJECT_FORMAT_VALUE); } }