Skip to content

Add option to fallback to non-pointer number, boolean types#23197

Merged
wing328 merged 3 commits intomasterfrom
23052-followup
Mar 10, 2026
Merged

Add option to fallback to non-pointer number, boolean types#23197
wing328 merged 3 commits intomasterfrom
23052-followup

Conversation

@wing328
Copy link
Member

@wing328 wing328 commented Mar 10, 2026

a follow up PR to #23052: add an option to avoid using pointers for number, boolean types

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 solves a reported issue, reference it using GitHub's linking syntax (e.g., having "fixes #123" present in the PR description)
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Adds an opt-in C libcurl generator option to emit non-pointer numeric and boolean fields using v7.20.0 model templates. Updates docs/config and regenerates the C petstore sample; includes a minor primitives list cleanup.

  • New Features

    • Adds declareNumberBooleanWithoutPointer (default: false) to the C libcurl generator.
    • When enabled, uses model-header-v7_20_0.mustache and model-body-v7_20_0.mustache to generate value types (int, long, etc.).
    • Updates docs and enables the option in bin/configs/c-useJsonUnformatted.yaml; regenerates samples/client/petstore/c-useJsonUnformatted showing non-pointer id, quantity, complete, etc.
  • Bug Fixes

    • Removes a duplicate int entry from C primitives in CLibcurlClientCodegen.

Written for commit 493fdee. Summary will update on new commits.

@wing328 wing328 marked this pull request as ready for review March 10, 2026 18:15
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

14 issues found across 20 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="samples/client/petstore/c-useJsonUnformatted/model/user.c">

<violation number="1" location="samples/client/petstore/c-useJsonUnformatted/model/user.c:116">
P2: Zero-valued numeric fields are now dropped during JSON serialization because pointer-style truthiness checks are still used with value types.</violation>

<violation number="2" location="samples/client/petstore/c-useJsonUnformatted/model/user.c:355">
P2: Inlining `strdup` into `user_create_internal` removed the failure cleanup path, causing leaks when model allocation fails.</violation>
</file>

<file name="samples/client/petstore/c-useJsonUnformatted/model/category.c">

<violation number="1" location="samples/client/petstore/c-useJsonUnformatted/model/category.c:106">
P2: `strdup(name->valuestring)` can leak if `category_create_internal` fails. Keep the duplicated string in a local variable and free it on creation failure.</violation>
</file>

<file name="samples/client/petstore/c-useJsonUnformatted/model/mapped_model.c">

<violation number="1" location="samples/client/petstore/c-useJsonUnformatted/model/mapped_model.c:105">
P2: Switching optional `another_property` to a plain `int` here causes explicit `0` values to be indistinguishable from “not set”, so `0` gets dropped during JSON serialization.</violation>
</file>

<file name="samples/client/petstore/c-useJsonUnformatted/model/pet.c">

<violation number="1" location="samples/client/petstore/c-useJsonUnformatted/model/pet.c:303">
P2: Handle `pet_create_internal` allocation failure in `pet_parseFromJSON`; the current direct return leaks already-allocated parse data (and the duplicated name string) when object creation fails.</violation>
</file>

<file name="samples/client/petstore/c-useJsonUnformatted/model/api_response.c">

<violation number="1" location="samples/client/petstore/c-useJsonUnformatted/model/api_response.c:134">
P2: `strdup` results are passed inline to `api_response_create_internal`, which leaks allocated strings if struct allocation fails.</violation>
</file>

<file name="samples/client/petstore/c-useJsonUnformatted/model/tag.h">

<violation number="1" location="samples/client/petstore/c-useJsonUnformatted/model/tag.h:22">
P2: Changing `id` to a non-pointer breaks serialization of valid `0` values because `tag_convertToJSON` now skips `id` when it is zero.</violation>
</file>

<file name="samples/client/petstore/c-useJsonUnformatted/model/order.c">

<violation number="1" location="samples/client/petstore/c-useJsonUnformatted/model/order.c:128">
P1: `complete=false` is now dropped during JSON serialization because scalar booleans are gated by a truthy check.</violation>

<violation number="2" location="samples/client/petstore/c-useJsonUnformatted/model/order.c:224">
P2: Inlining `strdup` into the constructor call leaks `ship_date` when `order_create_internal` fails.</violation>
</file>

<file name="samples/client/petstore/c-useJsonUnformatted/model/user.h">

<violation number="1" location="samples/client/petstore/c-useJsonUnformatted/model/user.h:31">
P2: Changing `user_status` to a non-pointer type causes `user_status = 0` to be skipped in JSON output due to `if(user->user_status)` checks.</violation>
</file>

<file name="samples/client/petstore/c-useJsonUnformatted/model/api_response.h">

<violation number="1" location="samples/client/petstore/c-useJsonUnformatted/model/api_response.h:22">
P1: Using a non-pointer `int` for `code` breaks JSON round-tripping for valid `0` values because serialization treats `0` as absent.</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/C-libcurl/model-body-v7_20_0.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/C-libcurl/model-body-v7_20_0.mustache:426">
P1: Required numeric/boolean fields are incorrectly rejected when their value is 0/false during JSON serialization.</violation>

<violation number="2" location="modules/openapi-generator/src/main/resources/C-libcurl/model-body-v7_20_0.mustache:864">
P0: Boolean array parsing stores raw ints as pointers, causing invalid dereference/free when serializing or destroying models.</violation>

<violation number="3" location="modules/openapi-generator/src/main/resources/C-libcurl/model-body-v7_20_0.mustache:924">
P0: Primitive map bool/number values are stored as pointers to cJSON internals, then freed as owned heap memory.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

{
goto end;
}
localMapKeyPair = keyValuePair_create(strdup(localMapObject->string), &localMapObject->valueint);
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0: Primitive map bool/number values are stored as pointers to cJSON internals, then freed as owned heap memory.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/C-libcurl/model-body-v7_20_0.mustache, line 924:

<comment>Primitive map bool/number values are stored as pointers to cJSON internals, then freed as owned heap memory.</comment>

<file context>
@@ -0,0 +1,1124 @@
+            {
+                goto end;
+            }
+            localMapKeyPair = keyValuePair_create(strdup(localMapObject->string), &localMapObject->valueint);
+            {{/isBoolean}}
+            {{#isNumeric}}
</file context>
Fix with Cubic

{
goto end;
}
list_addElement({{{name}}}List , {{{name}}}_local->valueint);
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0: Boolean array parsing stores raw ints as pointers, causing invalid dereference/free when serializing or destroying models.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/C-libcurl/model-body-v7_20_0.mustache, line 864:

<comment>Boolean array parsing stores raw ints as pointers, causing invalid dereference/free when serializing or destroying models.</comment>

<file context>
@@ -0,0 +1,1124 @@
+        {
+            goto end;
+        }
+        list_addElement({{{name}}}List , {{{name}}}_local->valueint);
+        {{/isBoolean}}
+        {{/items}}
</file context>
Fix with Cubic

// order->complete
if(order->complete) {
if(cJSON_AddBoolToObject(item, "complete", *order->complete) == NULL) {
if(cJSON_AddBoolToObject(item, "complete", order->complete) == NULL) {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: complete=false is now dropped during JSON serialization because scalar booleans are gated by a truthy check.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/c-useJsonUnformatted/model/order.c, line 128:

<comment>`complete=false` is now dropped during JSON serialization because scalar booleans are gated by a truthy check.</comment>

<file context>
@@ -168,7 +125,7 @@ cJSON *order_convertToJSON(order_t *order) {
     // order->complete
     if(order->complete) {
-    if(cJSON_AddBoolToObject(item, "complete", *order->complete) == NULL) {
+    if(cJSON_AddBoolToObject(item, "complete", order->complete) == NULL) {
     goto fail; //Bool
     }
</file context>
Fix with Cubic


typedef struct api_response_t {
int *code; //numeric
int code; //numeric
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Using a non-pointer int for code breaks JSON round-tripping for valid 0 values because serialization treats 0 as absent.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/c-useJsonUnformatted/model/api_response.h, line 22:

<comment>Using a non-pointer `int` for `code` breaks JSON round-tripping for valid `0` values because serialization treats `0` as absent.</comment>

<file context>
@@ -19,15 +19,15 @@ typedef struct api_response_t api_response_t;
 
 typedef struct api_response_t {
-    int *code; //numeric
+    int code; //numeric
     char *type; // string
     char *message; // string
</file context>
Fix with Cubic

// {{{classname}}}->{{{name}}}
{{#required}}
{{^isEnum}}
if (!{{{classname}}}->{{{name}}}) {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Required numeric/boolean fields are incorrectly rejected when their value is 0/false during JSON serialization.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/C-libcurl/model-body-v7_20_0.mustache, line 426:

<comment>Required numeric/boolean fields are incorrectly rejected when their value is 0/false during JSON serialization.</comment>

<file context>
@@ -0,0 +1,1124 @@
+    // {{{classname}}}->{{{name}}}
+    {{#required}}
+    {{^isEnum}}
+    if (!{{{classname}}}->{{{name}}}) {
+        goto fail;
+    }
</file context>
Fix with Cubic

id ? id->valuedouble : 0,
category ? category_local_nonprim : NULL,
name_local_str,
strdup(name->valuestring),
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Handle pet_create_internal allocation failure in pet_parseFromJSON; the current direct return leaks already-allocated parse data (and the duplicated name string) when object creation fails.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/c-useJsonUnformatted/model/pet.c, line 303:

<comment>Handle `pet_create_internal` allocation failure in `pet_parseFromJSON`; the current direct return leaks already-allocated parse data (and the duplicated name string) when object creation fails.</comment>

<file context>
@@ -321,35 +297,21 @@ pet_t *pet_parseFromJSON(cJSON *petJSON){
+        id ? id->valuedouble : 0,
         category ? category_local_nonprim : NULL,
-        name_local_str,
+        strdup(name->valuestring),
         photo_urlsList,
         tags ? tagsList : NULL,
</file context>
Fix with Cubic

type_local_str,
message_local_str
code ? code->valuedouble : 0,
type && !cJSON_IsNull(type) ? strdup(type->valuestring) : NULL,
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: strdup results are passed inline to api_response_create_internal, which leaks allocated strings if struct allocation fails.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/c-useJsonUnformatted/model/api_response.c, line 134:

<comment>`strdup` results are passed inline to `api_response_create_internal`, which leaks allocated strings if struct allocation fails.</comment>

<file context>
@@ -155,33 +129,14 @@ api_response_t *api_response_parseFromJSON(cJSON *api_responseJSON){
-        type_local_str,
-        message_local_str
+        code ? code->valuedouble : 0,
+        type && !cJSON_IsNull(type) ? strdup(type->valuestring) : NULL,
+        message && !cJSON_IsNull(message) ? strdup(message->valuestring) : NULL
         );
</file context>
Fix with Cubic


typedef struct tag_t {
long *id; //numeric
long id; //numeric
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Changing id to a non-pointer breaks serialization of valid 0 values because tag_convertToJSON now skips id when it is zero.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/c-useJsonUnformatted/model/tag.h, line 22:

<comment>Changing `id` to a non-pointer breaks serialization of valid `0` values because `tag_convertToJSON` now skips `id` when it is zero.</comment>

<file context>
@@ -19,14 +19,14 @@ typedef struct tag_t tag_t;
 
 typedef struct tag_t {
-    long *id; //numeric
+    long id; //numeric
     char *name; // string
 
</file context>
Fix with Cubic

id ? id->valuedouble : 0,
pet_id ? pet_id->valuedouble : 0,
quantity ? quantity->valuedouble : 0,
ship_date && !cJSON_IsNull(ship_date) ? strdup(ship_date->valuestring) : NULL,
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Inlining strdup into the constructor call leaks ship_date when order_create_internal fails.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/c-useJsonUnformatted/model/order.c, line 224:

<comment>Inlining `strdup` into the constructor call leaks `ship_date` when `order_create_internal` fails.</comment>

<file context>
@@ -289,52 +214,20 @@ order_t *order_parseFromJSON(cJSON *orderJSON){
+        id ? id->valuedouble : 0,
+        pet_id ? pet_id->valuedouble : 0,
+        quantity ? quantity->valuedouble : 0,
+        ship_date && !cJSON_IsNull(ship_date) ? strdup(ship_date->valuestring) : NULL,
         status ? statusVariable : openapi_petstore_order_STATUS_NULL,
-        complete_local_var
</file context>
Fix with Cubic

char *password; // string
char *phone; // string
int *user_status; //numeric
int user_status; //numeric
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Changing user_status to a non-pointer type causes user_status = 0 to be skipped in JSON output due to if(user->user_status) checks.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/c-useJsonUnformatted/model/user.h, line 31:

<comment>Changing `user_status` to a non-pointer type causes `user_status = 0` to be skipped in JSON output due to `if(user->user_status)` checks.</comment>

<file context>
@@ -21,29 +21,29 @@ typedef struct user_t user_t;
     char *password; // string
     char *phone; // string
-    int *user_status; //numeric
+    int user_status; //numeric
     list_t* extra; //map
     openapi_petstore_preference__e preference; //referenced enum
</file context>
Fix with Cubic

@wing328 wing328 added this to the 7.21.0 milestone Mar 10, 2026
@wing328 wing328 merged commit 1a09c7a into master Mar 10, 2026
22 checks passed
@wing328 wing328 deleted the 23052-followup branch March 10, 2026 18:35
davidricodias pushed a commit to davidricodias/openapi-generator that referenced this pull request Mar 11, 2026
…ools#23197)

* add option to fallback to non-pointe number, boolean

* add new files

* fix
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.

1 participant