Skip to content

Add option to set container's default to empty container #21269

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 27, 2025

Conversation

wing328
Copy link
Member

@wing328 wing328 commented May 13, 2025

Add option to set container's default to empty container using the generator's option defaultToEmptyContainer (this new option is supported by generators that respect the default value in the spec)

e.g.

set optional array and map default value to empty container

java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -o /tmp/output --additional-properties defaultToEmptyContainer="array?|map?"

set nullable array (required) default value to empty container

java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -o /tmp/output --additional-properties defaultToEmptyContainer="?array"

set nullable array (optional) default value to empty container

java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -o /tmp/output --additional-properties defaultToEmptyContainer="?array?"

to simply enable this option to respect default values in the spec (basically null if not specified):

java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -o /tmp/output --additional-properties defaultToEmptyContainer=""

to close #18735

PR checklist

  • Read the contribution guidelines.
  • Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work. Missing information here may result in delayed response from the community.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • File the PR against the correct branch: master (upcoming 7.x.0 minor release - breaking changes with fallbacks), 8.0.x (breaking changes without fallbacks)
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

@wing328 wing328 force-pushed the container-default-new branch from 7a71f9d to 4974932 Compare May 13, 2025 07:45
@wing328
Copy link
Member Author

wing328 commented May 13, 2025

To test this enhancement, please execute the following and replace petstore.yaml with your own spec

git clone --depth 1 https://github.com/OpenAPITools/openapi-generator/ -b container-default-new
cd openapi-generator
./mvnw clean package -DskipTests
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -o /tmp/output --additional-properties defaultToEmptyContainer="array?|map?"

For windows users using DOS prompt, please replace ./mvnw command with

mvnw.cmd clean package -DskipTests

@KristiAt
Copy link

Hi, I’ve tested the PR, specifically focusing on the case where we have a nullable, non-required array property. The current implementation would work if the default value were already null, but unfortunately that’s not the case.

Due to a regression introduced in version 7.5.0, such properties are now defaulting to empty arrays ([]) even when not required and marked as nullable. As a result, the behavior remains unchanged with this PR.

It would be very helpful if the new defaultToEmptyContainer option allowed us to explicitly opt out of setting a default altogether, preserving null for optional containers. That way, we could fully restore the expected behavior for nullable.

@wing328
Copy link
Member Author

wing328 commented May 16, 2025

thanks for testing it. i'll try to take another look this weekend

@wing328
Copy link
Member Author

wing328 commented May 18, 2025

@KristiAt can you please pull the latest to give it another try?

I've updated the PR with some fixes and tests.

@wing328
Copy link
Member Author

wing328 commented May 18, 2025

allowed us to explicitly opt out of setting a default altogether, preserving null for optional containers

I think that's the current behavior when the option is enabled - optional array is default to null (as its default value in the schema is null)

@KristiAt
Copy link

allowed us to explicitly opt out of setting a default altogether, preserving null for optional containers

I think that's the current behavior when the option is enabled - optional array is default to null (as its default value in the schema is null)

Hi,

I’ve tested the latest changes by both including array? in my POM file and excluding it altogether. However, the generated default is still an empty List.

I have a nullable, non-required parameter, and I would like its default value to remain null, rather than being serialized as an empty array. Currently, the only way I can achieve the desired behavior is by downgrading to version 7.4.0.

As shown in the image below, I would prefer the output to be undefined or null instead of an empty array.

Could you please advise if there's a configuration or update that supports this behavior in the latest version?

Thank you

Screenshot 2025-05-19 at 12 16 41

@wing328
Copy link
Member Author

wing328 commented May 19, 2025

nullable, non-required parameter, and I would like its default value to remain null,

for nullable optional properties, please use ?array?

array? means optional only (non-nullable) & ?array means nullable required

but the default value is null by default so looks like there's a bug with nullable optional. I'll add a test to confirm the behaviour.

@wing328
Copy link
Member Author

wing328 commented May 19, 2025

both including array? in my POM file and excluding it altogether. However, the generated default is still an empty List.

i think that's the expected behavior. whatever you provided in the defaultToEmptyContainer option will be default to an empty list/container/set etc.

enabling this option will respect the default value provided in the spec.

@wing328
Copy link
Member Author

wing328 commented May 19, 2025

just so we're on the same page. I try to generate an array (optional nullable) of integer with spring generator (library: spring-cloud) and this is what I got

  @Valid
  private JsonNullable<List<Integer>> integerNullableList = JsonNullable.<List<Integer>>undefined();

and you want to initalize it with null instead, i.e.

  @Valid
  private JsonNullable<List<Integer>> integerNullableList;

is my understanding correct?

@wing328
Copy link
Member Author

wing328 commented May 19, 2025

fyi. I tested with java client generator with proper defaultToEmptyContainer option and the result seems to meet your expectation:

  @SerializedName(SERIALIZED_NAME_INTEGER_NULLABLE_LIST)
  @javax.annotation.Nullable
  private List<Integer> integerNullableList;

@KristiAt
Copy link

KristiAt commented May 20, 2025

Hi, so I think this screenshot should help, this is the difference in behavior from 7.4.0 to 7.13.0 (same with your version).
How can I keep the old behavior form version 7.4.0 with your new changes specifically case r0, non-required?

Screenshot 2025-05-20 at 14 24 32

docs.yml inputSpec we used to test

openapi: 3.0.3
info:
  version: 1.0.0
  title: initialization demo
paths:
  /:
    get:
      responses:
        '200':
          description: dummy
          content:
            application/json:
              schema:
                type: object
                required:
                  - r1n0
                  - r1n1
                  - r1
                properties:
                  r0n0:
                    type: array
                    items:
                      type: string
                    nullable: false
                  r0n1:
                    type: array
                    items:
                      type: string
                    nullable: true
                  r1n0:
                    type: array
                    items:
                      type: string
                    nullable: false
                  r1n1:
                    type: array
                    items:
                      type: string
                    nullable: true
                  r0:
                    type: array
                    items:
                      type: string
                  r1:
                    type: array
                    items:
                      type: string

@wing328
Copy link
Member Author

wing328 commented May 21, 2025

using your spec with java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g spring --library spring-cloud -i /tmp/spring.yaml --additional-properties defaultToEmptyContainer="array" -o /tmp/spring5/

I got the following in src/main/java/org/openapitools/model/Get200Response.java

public class Get200Response {

  @Valid
  private @Nullable List<String> r0n0;

  @Valid
  private JsonNullable<List<String>> r0n1 = JsonNullable.<List<String>>undefined();

  @Valid
  private List<String> r1n0 = new ArrayList<>();

  @Valid
  private JsonNullable<List<String>> r1n1 = JsonNullable.<List<String>>undefined();

  @Valid
  private @Nullable List<String> r0;

  @Valid
  private List<String> r1 = new ArrayList<>();

  public Get200Response() {
    super();
  }

looks like this meet your requirement

defaultToEmptyContainer="array" means required (non-nullable) array will default to empty container.

@KristiAt
Copy link

Hi, thank you for your reply.

So I have managed to replicate your result running my command below (we use java not spring in -g option)

java -jar /Users/kristi.atanasova/Documents/Solidatus/solidatus-client-java/openapi-generator/modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i /Users/kristi.atanasova/Documents/Solidatus/solidatus-client-java/docs.yml --additional-properties defaultToEmptyContainer="array" -o /Users/kristi.atanasova/Documents/Solidatus/solidatus-client-java/generated3

Screenshot 2025-05-21 at 12 24 31

However, when I use the maven plugin I do not get the same result.

@wing328
Copy link
Member Author

wing328 commented May 21, 2025

However, when I use the maven plugin I do not get the same result.

Did you perform a mvn clean install -DskipTests to install the maven plugin built from this branch/PR so as to install the maven plugin to the local cache/store?

@KristiAt
Copy link

However, when I use the maven plugin I do not get the same result.

Did you perform a mvn clean install -DskipTests to install the maven plugin built from this branch/PR so as to install the maven plugin to the local cache/store?

Yes, I’ve installed version 7.14.0-SNAPSHOT with your changes. Could you please confirm if the usage of in my POM file is correct?

@wing328
Copy link
Member Author

wing328 commented May 21, 2025

Could you please confirm if the usage of in my POM file is correct?

should it be configOptions instead of additionalProperties?

e.g. https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator-maven-plugin/examples/java-client.xml#L35

@KristiAt
Copy link

Could you please confirm if the usage of in my POM file is correct?

should it be configOptions instead of additionalProperties?

e.g. https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator-maven-plugin/examples/java-client.xml#L35

Could you please confirm if the usage of in my POM file is correct?

should it be configOptions instead of additionalProperties?

e.g. https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator-maven-plugin/examples/java-client.xml#L35

It does not work. I tried it previously.

@wing328
Copy link
Member Author

wing328 commented May 23, 2025

can you change array to array|unknown in the defaultToEmptyContainer option instead with configOptions?

you should get the following in the log:

[main] ERROR o.o.codegen.DefaultCodegen - Skipped invalid container type `unknown` in the rule `array|unknown`.

that should confirm you're using the latest snapshot version built from this branch/pr

@wing328
Copy link
Member Author

wing328 commented May 23, 2025

Just to make sure. You did pull the latest changes (commits) to your local branch before rebuilding the JARs, right?

@KristiAt
Copy link

Just to make sure. You did pull the latest changes (commits) to your local branch before rebuilding the JARs, right?

Yes, I can see your code changes from this draft. I am unable to figure out the correct way of using this new parameter in my pom file.

@wing328
Copy link
Member Author

wing328 commented May 23, 2025

[main] ERROR o.o.codegen.DefaultCodegen - Skipped invalid container type unknown in the rule array|unknown.

are you able to repeat the error message in your end?

@wing328 wing328 marked this pull request as ready for review May 26, 2025 02:34
@bodograumann
Copy link
Contributor

I tested the pr branch with our spec by setting the new property to the empty string and it works. No default values are generated anymore.

@wing328
Copy link
Member Author

wing328 commented May 26, 2025

@bodograumann thanks for testing the change to confirm it works for your use cases

@KristiAt
Copy link

[main] ERROR o.o.codegen.DefaultCodegen - Skipped invalid container type unknown in the rule array|unknown.

are you able to repeat the error message in your end?

No, I'm having trouble finding the correct syntax to add a parameter to my pom.xml file. The command works as expected when passed via the CLI, but I haven’t been able to get it working through the POM configuration.

I've tried the following approaches, but none have worked:

<additionalProperties>
    <defaultToEmptyContainer>array|undefined</defaultToEmptyContainer>
</additionalProperties>

<additionalProperties>defaultToEmptyContainer=array|undefined</additionalProperties>

<configOptions>
        <defaultToEmptyContainer>array|undefined</defaultToEmptyContainer>
</configOptions>

@wing328
Copy link
Member Author

wing328 commented May 27, 2025

@KristiAt I'll take another look later this week. looks like a maven plugin usage issue

For the time being, I'll merge this PR so that more users can try it out.

@wing328 wing328 merged commit 2c67841 into master May 27, 2025
88 checks passed
@wing328 wing328 deleted the container-default-new branch May 27, 2025 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG][JAVA] optional collection fields are initialized since 7.5.0
3 participants