Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,20 @@ components:
type: string
example: "94022"
```
#### 5. explicitObjectSchema:

```java
ParseOptions parseOptions = new ParseOptions();
parseOptions.setResolve(true); // implicit
parseOptions.setResolveFully(true);
parseOptions.setResolveCombinators(false);
parseOptions.setExplicitObjectSchema(false); // default is true
final OpenAPI openAPI = new OpenAPIV3Parser().read("a.yaml", null, parseOptions);
```

This option allows you to customize the processing of schema properties when the type is not specified. By default it is set to `true`.
- `true` : when the type is not defined for property, ‘object’ is set.
- `false` : the property remains undefined when no type is specified

### Extensions
This project has a core artifact--`swagger-parser`, which uses Java Service Provider Interface (SPI) so additional extensions can be added.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class ParseOptions {
private List<String> remoteRefAllowList;
private List<String> remoteRefBlockList;
private boolean explicitStyleAndExplode = true;
private boolean explicitObjectSchema = true;


public boolean isResolve() {
Expand Down Expand Up @@ -179,4 +180,12 @@ public void setExplicitStyleAndExplode(boolean explicitStyleAndExplode) {
this.explicitStyleAndExplode = explicitStyleAndExplode;
}

public boolean isExplicitObjectSchema() {
return explicitObjectSchema;
}

public void setExplicitObjectSchema(boolean explicitObjectSchema) {
this.explicitObjectSchema = explicitObjectSchema;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ private SwaggerParseResult readResult(SwaggerDeserializationResult result, List<
SwaggerParseResult out = convert(result);
if (out != null && out.getOpenAPI() != null && options != null) {
if (options.isResolveFully()) {
new ResolverFully(options.isResolveCombinators()).resolveFully(out.getOpenAPI());
new ResolverFully(options).resolveFully(out.getOpenAPI());
}
if (options.isFlatten()) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ private SwaggerParseResult resolve(SwaggerParseResult result, List<Authorization
dereferencer.dereference(dereferencerContext, dereferencers.iterator());
}
if (options.isResolveFully()) {
new ResolverFully(options.isResolveCombinators()).resolveFully(result.getOpenAPI());
new ResolverFully(options).resolveFully(result.getOpenAPI());
}
} else {
String msg = "Resolution of OAS 3.1 spec disabled by 'disableOas31Resolve' env variable";
Expand All @@ -239,7 +239,7 @@ private SwaggerParseResult resolve(SwaggerParseResult result, List<Authorization
location, null, options);
resolver.resolve(result);
if (options.isResolveFully()) {
new ResolverFully(options.isResolveCombinators()).resolveFully(result.getOpenAPI());
new ResolverFully(options).resolveFully(result.getOpenAPI());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
import io.swagger.v3.parser.core.models.ParseOptions;
import io.swagger.v3.parser.models.RefFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -38,14 +39,15 @@ public class ResolverFully {

private boolean aggregateCombinators;

private ParseOptions parseOptions;
Copy link
Contributor

Choose a reason for hiding this comment

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

I would initialize this to new ParseOptions() to avoid NPEs if folks keep using other constructors

Copy link
Contributor Author

@daniel-kmiecik daniel-kmiecik Jun 17, 2025

Choose a reason for hiding this comment

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

done



public ResolverFully() {
this(true);
}

public ResolverFully(boolean aggregateCombinators) {
this.aggregateCombinators = aggregateCombinators;
public ResolverFully(ParseOptions options) {
if (options != null) {
this.aggregateCombinators = options.isResolveCombinators();
} else {
this.aggregateCombinators = true;
}
this.parseOptions = options;
}

private Map<String, Schema> schemas;
Expand Down Expand Up @@ -493,7 +495,7 @@ public Schema resolveSchema(Schema schema) {
Schema property = updated.get(key);

if (property.getProperties() != model.getProperties()) {
if (!hasSchemaType(property)) {
if (!hasSchemaType(property) && parseOptions.isExplicitObjectSchema()) {
if (SpecVersion.V30.equals(property.getSpecVersion())) {
property.setType("object");
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.io.File;
Expand Down Expand Up @@ -597,7 +598,7 @@ public void testSelfReferenceResolution()throws Exception {
options.setResolveFully(true);

OpenAPI openAPI = new OpenAPIV3Parser().readContents(yaml,auths,options).getOpenAPI();
ResolverFully resolverUtil = new ResolverFully();
ResolverFully resolverUtil = new ResolverFully(options);
resolverUtil.resolveFully(openAPI);


Expand Down Expand Up @@ -643,7 +644,7 @@ public void testIssue85() {
options.setResolveFully(true);

OpenAPI openAPI = new OpenAPIV3Parser().readContents(yaml,auths,options).getOpenAPI();
ResolverFully resolverUtil = new ResolverFully();
ResolverFully resolverUtil = new ResolverFully(options);
resolverUtil.resolveFully(openAPI);
Parameter param = openAPI.getPaths().get("/test/method").getPost().getParameters().get(0);

Expand Down Expand Up @@ -1475,5 +1476,29 @@ public void testResolveArraySchemaItemsNullPointerException() {
final OpenAPI output = new OpenAPIV3Parser().read(actualLocation, null, options);
new OpenAPIResolver(output, null, actualLocation).resolve();
}

@Test(dataProvider = "explicitObjectSchemaProvider")
public void testIssue2113(boolean explicitObjectSchema) {
ParseOptions options = new ParseOptions();
options.setResolve(true);
options.setResolveFully(true);
options.setExplicitObjectSchema(explicitObjectSchema);

OpenAPI openAPI = new OpenAPIV3Parser().readLocation("issue_2113.yaml", auths, options).getOpenAPI();
ObjectSchema schema = (ObjectSchema) openAPI.getPaths().get("/foo").getPost().getRequestBody().getContent().get("application/json").getSchema();
if (explicitObjectSchema) {
assertEquals(schema.getProperties().get("goo").getType(), "object");
} else {
assertNull(schema.getProperties().get("goo").getType());
}
}

@DataProvider(name = "explicitObjectSchemaProvider")
public Object[][] explicitObjectSchemaProvider() {
return new Object[][] {
{ true },
{ false }
};
}

}
28 changes: 28 additions & 0 deletions modules/swagger-parser-v3/src/test/resources/issue_2113.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
openapi: "3.0.0"
info:
version: 1.0.0
title: Issue X
servers:
- url: http://petstore.swagger.io/api
paths:
/foo:
post:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/ObjectType'
required: true
responses:
200:
description: ok
components:
schemas:
ObjectType:
type: object
allOf:
- $ref: "#/components/schemas/NoType"
NoType:
properties:
goo:
title: "Boo"
Loading