Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3645,7 +3645,7 @@ protected void setAddProps(Schema schema, IJsonSchemaValidationProperties proper
addPropProp = fromProperty(getAdditionalPropertiesName(), new Schema(), false);
additionalPropertiesIsAnyType = true;
}
} else {
} else if (!isBooleanSchemaFalse(schema.getAdditionalProperties())) {
// if additional properties is set (e.g. free form object, any type, string, etc)
addPropProp = fromProperty(getAdditionalPropertiesName(), (Schema) schema.getAdditionalProperties(), false);
additionalPropertiesIsAnyType = true;
Expand All @@ -3664,6 +3664,12 @@ protected void setAddProps(Schema schema, IJsonSchemaValidationProperties proper
}
}

// OAS 3.1 can parse `additionalProperties: false` as a boolean schema instead of Boolean.FALSE
private static boolean isBooleanSchemaFalse(Object additionalProperties) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: This helper repeats the false-boolean additionalProperties check that ModelUtils.isMapSchema and ModelUtils.isModelWithPropertiesOnly already inline. Move it to ModelUtils as a public static method and call it from both places, so the OAS 3.1 closed-schema rule lives in one place.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java, line 3668:

<comment>This helper repeats the false-boolean `additionalProperties` check that `ModelUtils.isMapSchema` and `ModelUtils.isModelWithPropertiesOnly` already inline. Move it to `ModelUtils` as a public static method and call it from both places, so the OAS 3.1 closed-schema rule lives in one place.</comment>

<file context>
@@ -3664,6 +3664,12 @@ protected void setAddProps(Schema schema, IJsonSchemaValidationProperties proper
     }
 
+    // OAS 3.1 can parse `additionalProperties: false` as a boolean schema instead of Boolean.FALSE
+    private static boolean isBooleanSchemaFalse(Object additionalProperties) {
+        return additionalProperties instanceof Schema
+                && Boolean.FALSE.equals(((Schema) additionalProperties).getBooleanSchemaValue());
</file context>

return additionalProperties instanceof Schema
&& Boolean.FALSE.equals(((Schema) additionalProperties).getBooleanSchemaValue());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: The checked-in OpenAPI input uses additionalProperties: {} for PropertiesWithAnyOf, but this regeneration removes its AdditionalProperties dictionary. Preserve open empty schemas; only suppress the member for an actual boolean-false schema.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java, line 3670:

<comment>The checked-in OpenAPI input uses `additionalProperties: {}` for `PropertiesWithAnyOf`, but this regeneration removes its `AdditionalProperties` dictionary. Preserve open empty schemas; only suppress the member for an actual boolean-false schema.</comment>

<file context>
@@ -3664,6 +3664,12 @@ protected void setAddProps(Schema schema, IJsonSchemaValidationProperties proper
+    // OAS 3.1 can parse `additionalProperties: false` as a boolean schema instead of Boolean.FALSE
+    private static boolean isBooleanSchemaFalse(Object additionalProperties) {
+        return additionalProperties instanceof Schema
+                && Boolean.FALSE.equals(((Schema) additionalProperties).getBooleanSchemaValue());
+    }
+
</file context>

}

/**
* Recursively look in Schema sc for the discriminator and return it
*
Expand Down Expand Up @@ -8592,7 +8598,7 @@ protected void addRequiredVarsMap(Schema schema, IJsonSchemaValidationProperties
if (!found) {
LOGGER.warn("Property {} is not processed correctly (missing from getVars). Maybe it's a const (not yet supported) in openapi v3.1 spec.", requiredPropertyName);
}
} else if (schema.getAdditionalProperties() instanceof Boolean && Boolean.FALSE.equals(schema.getAdditionalProperties())) {
} else if (Boolean.FALSE.equals(schema.getAdditionalProperties()) || isBooleanSchemaFalse(schema.getAdditionalProperties())) {
// TODO add processing for requiredPropertyName
// required property is not defined in properties, and additionalProperties is false, value is null
requiredVarsMap.put(usedRequiredPropertyName, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,23 @@ public void testGenerateJsonNullableListFieldsHelperMethodReferences_issue23251(
output.deleteOnExit();
}

@Test
public void testClosedSchemaWithInlineMapPropertyHasNoAdditionalPropertiesAccessors_issue25430() throws Exception {
File output = Files.createTempDirectory("test").toFile();
output.deleteOnExit();

final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("jaxrs-spec")
.setInputSpec("src/test/resources/3_1/issue_25430.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));

new DefaultGenerator().opts(configurator.toClientOptInput()).generate();

Path model = output.toPath().resolve("src/gen/java/org/openapitools/model/PatchRequest.java");
assertFileContains(model, "public class PatchRequest ", "private Map<String, Object> context");
assertFileNotContains(model, "extends HashMap", "putAdditionalProperty", "getAdditionalProperties");
}

@Test
public void testJsonNullableContainerDefaultIsDeclared() throws Exception {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
Expand Down
25 changes: 25 additions & 0 deletions modules/openapi-generator/src/test/resources/3_1/issue_25430.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
openapi: 3.1.0
info:
title: Closed schema with an inline map property (issue 25430)
version: 1.0.0
paths:
/patch:
post:
operationId: patch
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/PatchRequest"
responses:
"204":
description: No content
components:
schemas:
PatchRequest:
type: object
properties:
context:
type: object
additionalProperties: true
additionalProperties: false

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: This fixture only covers the setAddProps change. Add a required entry for a property not declared in properties (for example required: [missing]) to PatchRequest, and assert the generated model in the test. That exercises the addRequiredVarsMap change, which the test does not currently cover.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At modules/openapi-generator/src/test/resources/3_1/issue_25430.yaml, line 25:

<comment>This fixture only covers the `setAddProps` change. Add a `required` entry for a property not declared in `properties` (for example `required: [missing]`) to `PatchRequest`, and assert the generated model in the test. That exercises the `addRequiredVarsMap` change, which the test does not currently cover.</comment>

<file context>
@@ -0,0 +1,25 @@
+        context:
+          type: object
+          additionalProperties: true
+      additionalProperties: false
</file context>

Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,6 @@ public PropertiesWithAnyOf(Option<decimal?> anyofNullableNumber = default, Optio
[JsonPropertyName("anyof_nullable_string")]
public string? AnyofNullableString { get { return this.AnyofNullableStringOption.Value; } set { this.AnyofNullableStringOption = new(value); } }

/// <summary>
/// Gets or Sets additional properties
/// </summary>
[JsonExtensionData]
public Dictionary<string, JsonElement> AdditionalProperties { get; } = new Dictionary<string, JsonElement>();

/// <summary>
/// Returns the string presentation of the object
/// </summary>
Expand All @@ -88,7 +82,6 @@ public override string ToString()
sb.Append("class PropertiesWithAnyOf {\n");
sb.Append(" AnyofNullableNumber: ").Append(AnyofNullableNumber).Append("\n");
sb.Append(" AnyofNullableString: ").Append(AnyofNullableString).Append("\n");
sb.Append(" AdditionalProperties: ").Append(AdditionalProperties).Append("\n");
sb.Append("}\n");
return sb.ToString();
}
Expand Down
Loading