Skip to content

Commit

Permalink
[Go] Set Default Values for Required Variables when a default is defi…
Browse files Browse the repository at this point in the history
…ned (OpenAPITools#19232)

* use default values for required vars when available

* update tests to existing config file

* cleanup OAS test

* Remove setting value in Get.

* Use Pascal Case for variable naming in Getter Function

* add a CLI option

* add a CLI option

* add a CLI option
  • Loading branch information
vvb authored and mohamuni committed Aug 1, 2024
1 parent 26a164e commit cb44d5b
Show file tree
Hide file tree
Showing 38 changed files with 413 additions and 23 deletions.
1 change: 1 addition & 0 deletions bin/configs/go-petstore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ additionalProperties:
packageName: petstore
disallowAdditionalPropertiesIfNotPresent: false
generateInterfaces: true
useDefaultValuesForRequiredVars: "true"
enumNameMappings:
delivered: SHIPPED

1 change: 1 addition & 0 deletions docs/generators/go.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|packageVersion|Go package version.| |1.0.0|
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|structPrefix|whether to prefix struct with the class name. e.g. DeletePetOpts => PetApiDeletePetOpts| |false|
|useDefaultValuesForRequiredVars|Use default values for required variables when available| |false|
|useOneOfDiscriminatorLookup|Use the discriminator's mapping in oneOf to speed up the model lookup. IMPORTANT: Validation (e.g. one and only one match in oneOf's schemas) will be skipped.| |false|
|withAWSV4Signature|whether to include AWS v4 signature support| |false|
|withGoMod|Generate go.mod and go.sum| |true|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -449,4 +449,6 @@ public static enum ENUM_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case,
public static final String MAX_ATTEMPTS_FOR_RETRY = "maxAttemptsForRetry";

public static final String WAIT_TIME_OF_THREAD = "waitTimeMillis";

public static final String USE_DEFAULT_VALUES_FOR_REQUIRED_VARS = "useDefaultValuesForRequiredVars";
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,26 @@ public abstract class AbstractGoCodegen extends DefaultCodegen implements Codege
private final Logger LOGGER = LoggerFactory.getLogger(AbstractGoCodegen.class);
private static final String NUMERIC_ENUM_PREFIX = "_";

@Setter protected boolean withGoCodegenComment = false;
@Setter protected boolean withAWSV4Signature = false;
@Setter protected boolean withXml = false;
@Setter protected boolean enumClassPrefix = false;
@Setter protected boolean structPrefix = false;
@Setter protected boolean generateInterfaces = false;
@Setter protected boolean withGoMod = false;
@Setter protected boolean generateMarshalJSON = true;
@Setter protected boolean generateUnmarshalJSON = true;
@Setter
protected boolean withGoCodegenComment = false;
@Setter
protected boolean withAWSV4Signature = false;
@Setter
protected boolean withXml = false;
@Setter
protected boolean enumClassPrefix = false;
@Setter
protected boolean structPrefix = false;
@Setter
protected boolean generateInterfaces = false;
@Setter
protected boolean withGoMod = false;
@Setter
protected boolean generateMarshalJSON = true;
@Setter
protected boolean generateUnmarshalJSON = true;
@Setter
protected boolean useDefaultValuesForRequiredVars = false;

@Setter protected String packageName = "openapi";
protected Set<String> numberTypes;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public class GoClientCodegen extends AbstractGoCodegen {
public static final String GENERATE_INTERFACES = "generateInterfaces";
public static final String MODEL_FILE_FOLDER = "modelFileFolder";
public static final String WITH_GO_MOD = "withGoMod";
public static final String USE_DEFAULT_VALUES_FOR_REQUIRED_VARS = "useDefaultValuesForRequiredVars";
@Setter protected String goImportAlias = "openapiclient";
protected boolean isGoSubmodule = false;
@Setter protected boolean useOneOfDiscriminatorLookup = false; // use oneOf discriminator's mapping for model lookup
Expand Down Expand Up @@ -126,6 +127,7 @@ public GoClientCodegen() {
cliOptions.add(CliOption.newBoolean(STRUCT_PREFIX, "whether to prefix struct with the class name. e.g. DeletePetOpts => PetApiDeletePetOpts"));
cliOptions.add(CliOption.newBoolean(WITH_AWSV4_SIGNATURE, "whether to include AWS v4 signature support"));
cliOptions.add(CliOption.newBoolean(GENERATE_INTERFACES, "Generate interfaces for api classes"));
cliOptions.add(CliOption.newBoolean(USE_DEFAULT_VALUES_FOR_REQUIRED_VARS, "Use default values for required variables when available"));

// option to change the order of form/body parameter
cliOptions.add(CliOption.newBoolean(
Expand Down Expand Up @@ -246,6 +248,11 @@ public void processOpts() {
additionalProperties.put(GENERATE_INTERFACES, generateInterfaces);
}

if (additionalProperties.containsKey(USE_DEFAULT_VALUES_FOR_REQUIRED_VARS)) {
setUseDefaultValuesForRequiredVars(Boolean.parseBoolean(additionalProperties.get(USE_DEFAULT_VALUES_FOR_REQUIRED_VARS).toString()));
additionalProperties.put(USE_DEFAULT_VALUES_FOR_REQUIRED_VARS, useDefaultValuesForRequiredVars);
}

// Generate the 'signing.py' module, but only if the 'HTTP signature' security scheme is specified in the OAS.
Map<String, SecurityScheme> securitySchemeMap = openAPI != null ?
(openAPI.getComponents() != null ? openAPI.getComponents().getSecuritySchemes() : null) : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,18 @@ func (o *{{classname}}) Set{{name}}(v {{vendorExtensions.x-go-base-type}}) {
{{/isNullable}}
}

{{#useDefaultValuesForRequiredVars}}
{{^isReadOnly}}
{{#defaultValue}}
// GetDefault{{baseName}} function assigns the default value {{defaultValue}} to the {{name}} field
// of the {{classname}} struct and returns the {{{defaultValue}}}.
func (o *{{classname}}) GetDefault{{nameInPascalCase}}() interface{} {
return {{{defaultValue}}}
}
{{/defaultValue}}
{{/isReadOnly}}
{{/useDefaultValuesForRequiredVars}}

{{/required}}
{{^required}}
// Get{{name}} returns the {{name}} field value if set, zero value otherwise{{#isNullable}} (both if not set or set to explicit null){{/isNullable}}.
Expand Down Expand Up @@ -318,6 +330,15 @@ func (o {{classname}}) ToMap() (map[string]interface{}, error) {
{{! if argument is not nullable, don't set it if it is nil}}
{{^isNullable}}
{{#required}}
{{#useDefaultValuesForRequiredVars}}
{{^isReadOnly}}
{{#defaultValue}}
if _, exists := toSerialize["{{{baseName}}}"]; !exists {
toSerialize["{{{baseName}}}"] = o.GetDefault{{nameInPascalCase}}()
}
{{/defaultValue}}
{{/isReadOnly}}
{{/useDefaultValuesForRequiredVars}}
toSerialize["{{{baseName}}}"] = o.{{name}}
{{/required}}
{{^required}}
Expand Down Expand Up @@ -356,6 +377,20 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
{{/requiredVars}}
}
{{#useDefaultValuesForRequiredVars}}
// defaultValueFuncMap captures the default values for required properties.
// These values are used when required properties are missing from the payload.
defaultValueFuncMap := map[string]func() interface{} {
{{#requiredVars}}
{{#defaultValue}}
{{^isReadOnly}}
"{{baseName}}": o.GetDefault{{nameInPascalCase}},
{{/isReadOnly}}
{{/defaultValue}}
{{/requiredVars}}
}
var defaultValueApplied bool
{{/useDefaultValuesForRequiredVars}}
allProperties := make(map[string]interface{})
err = json.Unmarshal(data, &allProperties)
Expand All @@ -365,11 +400,30 @@ func (o *{{{classname}}}) UnmarshalJSON(data []byte) (err error) {
}
for _, requiredProperty := range(requiredProperties) {
{{#useDefaultValuesForRequiredVars}}
if value, exists := allProperties[requiredProperty]; !exists || value == "" {
if _, ok := defaultValueFuncMap[requiredProperty]; ok {
allProperties[requiredProperty] = defaultValueFuncMap[requiredProperty]()
defaultValueApplied = true
}
}
if value, exists := allProperties[requiredProperty]; !exists || value == ""{
{{/useDefaultValuesForRequiredVars}}
{{^useDefaultValuesForRequiredVars}}
if _, exists := allProperties[requiredProperty]; !exists {
{{/useDefaultValuesForRequiredVars}}
return fmt.Errorf("no value given for required property %v", requiredProperty)
}
}
{{#useDefaultValuesForRequiredVars}}
if defaultValueApplied {
data, err = json.Marshal(allProperties)
if err != nil{
return err
}
}
{{/useDefaultValuesForRequiredVars}}
{{/hasRequired}}
{{#isAdditionalPropertiesTrue}}
{{#parent}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,6 @@ protected void verifyOptions() {
verify(clientCodegen).setWithGoMod(GoClientOptionsProvider.WITH_GO_MOD_VALUE);
verify(clientCodegen).setGenerateMarshalJSON(GoClientOptionsProvider.GENERATE_MARSHAL_JSON_VALUE);
verify(clientCodegen).setGenerateUnmarshalJSON(GoClientOptionsProvider.GENERATE_UNMARSHAL_JSON_VALUE);
verify(clientCodegen).setUseDefaultValuesForRequiredVars(GoClientOptionsProvider.USE_DEFAULT_VALUES_FOR_REQUIRED_VARS_VALUE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class GoClientOptionsProvider implements OptionsProvider {
public static final boolean WITH_GO_MOD_VALUE = true;
public static final boolean GENERATE_MARSHAL_JSON_VALUE = true;
public static final boolean GENERATE_UNMARSHAL_JSON_VALUE = true;
public static final boolean USE_DEFAULT_VALUES_FOR_REQUIRED_VARS_VALUE = true;

@Override
public String getLanguage() {
Expand All @@ -64,6 +65,7 @@ public Map<String, String> createOptions() {
.put(CodegenConstants.GENERATE_UNMARSHAL_JSON, "true")
.put("generateInterfaces", "true")
.put("structPrefix", "true")
.put(CodegenConstants.USE_DEFAULT_VALUES_FOR_REQUIRED_VARS, "true")
.build();
}

Expand Down
2 changes: 2 additions & 0 deletions samples/client/echo_api/go-external-refs/model_pet.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions samples/client/echo_api/go/model_pet.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions samples/client/petstore/go/go-petstore/model_animal.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions samples/client/petstore/go/go-petstore/model_category.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions samples/client/petstore/go/go-petstore/model_enum_test_.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions samples/client/petstore/go/go-petstore/model_format_test_.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions samples/client/petstore/go/go-petstore/model_name.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit cb44d5b

Please sign in to comment.