Skip to content

Commit 13cd478

Browse files
Mattias-Sehlstedtewaostrowska
authored andcommitted
fix: OAS 3.1 schema generation for raw Object properties is controlled with explicit-object-schema flag
1 parent 576ea45 commit 13cd478

File tree

9 files changed

+69
-35
lines changed

9 files changed

+69
-35
lines changed

modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -602,9 +602,7 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context
602602
} else if (hasCompositionKeywords) {
603603
model = openapi31 ? new JsonSchema() : new ComposedSchema();
604604
model.name(name);
605-
if (
606-
(openapi31 && Boolean.TRUE.equals(PrimitiveType.explicitObjectType)) ||
607-
(!openapi31 && (!Boolean.FALSE.equals(PrimitiveType.explicitObjectType)))) {
605+
if (isExplicitObjectType()) {
608606
if (openapi31 && resolvedArrayAnnotation == null) {
609607
model.addType("object");
610608
} else {
@@ -620,8 +618,7 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context
620618
return model;
621619
} else {
622620
model = openapi31 ? new JsonSchema().name(name) : new Schema().name(name);
623-
if ((openapi31 && Boolean.TRUE.equals(PrimitiveType.explicitObjectType)) ||
624-
(!openapi31 && (!Boolean.FALSE.equals(PrimitiveType.explicitObjectType)))) {
621+
if (isExplicitObjectType()) {
625622
if (openapi31 && resolvedArrayAnnotation == null) {
626623
model.addType("object");
627624
} else {
@@ -3572,4 +3569,9 @@ private boolean isStreamType(JavaType type) {
35723569
type.getRawClass() != null &&
35733570
java.util.stream.Stream.class.isAssignableFrom(type.getRawClass());
35743571
}
3572+
3573+
private boolean isExplicitObjectType() {
3574+
return (openapi31 && Boolean.TRUE.equals(PrimitiveType.explicitObjectType)) ||
3575+
(!openapi31 && (!Boolean.FALSE.equals(PrimitiveType.explicitObjectType)));
3576+
}
35753577
}

modules/swagger-core/src/main/java/io/swagger/v3/core/util/PrimitiveType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ public Schema createProperty() {
239239
}
240240
@Override
241241
public Schema createProperty31() {
242-
return explicitObjectType == null || explicitObjectType ? new JsonSchema().typesItem("object") : new JsonSchema();
242+
return Boolean.TRUE.equals(explicitObjectType) ? new JsonSchema().typesItem("object") : new JsonSchema();
243243
}
244244
};
245245

modules/swagger-core/src/test/java/io/swagger/v3/core/resolving/v31/ModelResolverOAS31Test.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,7 @@ public void testOAS31Fields() {
240240
" creditCard:\n" +
241241
" $ref: \"#/components/schemas/CreditCard\"\n" +
242242
" properties:\n" +
243-
" extraObject:\n" +
244-
" type: object\n" +
243+
" extraObject: {}\n" +
245244
"MultipleBaseBean:\n" +
246245
" type: object\n" +
247246
" description: MultipleBaseBean\n" +

modules/swagger-core/src/test/java/io/swagger/v3/core/serialization/Oas31ObjectFieldTest.java

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.swagger.v3.core.serialization;
22

33
import io.swagger.v3.core.converter.ModelConverters;
4+
import io.swagger.v3.core.util.PrimitiveType;
45
import io.swagger.v3.oas.models.media.Schema;
56
import org.testng.Assert;
67
import org.testng.annotations.Test;
@@ -9,19 +10,56 @@
910
import java.util.Map;
1011

1112
public class Oas31ObjectFieldTest {
12-
@Test(description = "Repro #4682: In OAS 3.1, raw Object property should not be rendered as an empty schema")
13-
public void rawObjectPropertyShouldBeObjectSchema() {
13+
14+
@Test(description = "Regression test for #4868: In OAS 3.1, raw Object property should be rendered as an empty schema")
15+
public void rawObjectPropertyShouldBeEmptySchema() {
1416
Map<String, Schema> schemas = ModelConverters.getInstance(true).readAll(PojoUsingObjectField.class);
1517
Schema pojo = schemas.get("PojoUsingObjectField");
1618
Assert.assertNotNull(pojo, "PojoUsingObjectField schema should exist");
19+
Schema myField = (Schema) pojo.getProperties().get("myField");
20+
Assert.assertNotNull(myField, "myField schema should exist");
21+
Assert.assertNull(myField.getTypes(), "Expected raw Object property to be an empty schema in OAS 3.1, but was: type=" + myField.getType() + ", types=" + myField.getTypes() + ", class=" + myField.getClass());
22+
}
1723

24+
@Test(description = "Regression test for #4868: OAS 3.1: List<Object> items schema should be empty")
25+
public void listOfObjectItemsShouldBeEmptySchema() {
26+
Map<String, Schema> schemas = ModelConverters.getInstance(true).readAll(PojoUsingListOfObject.class);
27+
Schema pojo = schemas.get("PojoUsingListOfObject");
28+
Assert.assertNotNull(pojo, "PojoUsingListOfObject schema should exist");
29+
Schema itemsProp = (Schema) pojo.getProperties().get("items");
30+
Assert.assertNotNull(itemsProp, "items property schema should exist");
31+
Schema itemSchema = itemsProp.getItems();
32+
Assert.assertNotNull(itemSchema, "List<Object> items schema should exist");
33+
Assert.assertNull(itemSchema.getTypes(), "Expected List<Object> items to be an empty schema in OAS 3.1, but was: type=" + itemSchema.getType() + ", types=" + itemSchema.getTypes() + ", class=" + itemSchema.getClass());
34+
}
35+
36+
@Test(description = "Regression test for #4868: OAS 3.1: Map<String,Object> additionalProperties schema should be empty")
37+
public void mapOfObjectAdditionalPropertiesShouldBeEmptySchema() {
38+
Map<String, Schema> schemas = ModelConverters.getInstance(true).readAll(PojoUsingMapStringToObject.class);
39+
Schema pojo = schemas.get("PojoUsingMapStringToObject");
40+
Assert.assertNotNull(pojo, "PojoUsingMapStringToObject schema should exist");
41+
Schema additionalProp = (Schema) pojo.getProperties().get("additional");
42+
Assert.assertNotNull(additionalProp, "additional property schema should exist");
43+
Schema valueSchema = (Schema) additionalProp.getAdditionalProperties();
44+
Assert.assertNotNull(valueSchema, "Map<String,Object> additionalProperties (value schema) should exist");
45+
Assert.assertNull(valueSchema.getTypes(), "Expected Map<String,Object> additionalProperties to be an empty schema in OAS 3.1, but was: type=" + valueSchema.getType() + ", types=" + valueSchema.getTypes() + ", class=" + valueSchema.getClass());
46+
}
47+
48+
@Test(description = "Repro #4682: In OAS 3.1, raw Object property should not be rendered as an empty schema if explicit-object-schema is enabled")
49+
public void rawObjectPropertyShouldBeObjectSchema() {
50+
setExplicitTypeObject(true);
51+
Map<String, Schema> schemas = ModelConverters.getInstance(true).readAll(PojoUsingObjectField.class);
52+
Schema pojo = schemas.get("PojoUsingObjectField");
53+
Assert.assertNotNull(pojo, "PojoUsingObjectField schema should exist");
1854
Schema myField = (Schema) pojo.getProperties().get("myField");
1955
Assert.assertNotNull(myField, "myField schema should exist");
2056
Assert.assertTrue(isObjectSchema(myField), "Expected raw Object property to be an object schema in OAS 3.1, but was: type=" + myField.getType() + ", types=" + myField.getTypes() + ", class=" + myField.getClass());
57+
setExplicitTypeObject(null);
2158
}
2259

23-
@Test(description = "OAS 3.1: List<Object> items schema should be object")
60+
@Test(description = "OAS 3.1: List<Object> items schema should be object if explicit-object-schema is enabled")
2461
public void listOfObjectItemsShouldBeObjectSchema() {
62+
setExplicitTypeObject(true);
2563
Map<String, Schema> schemas = ModelConverters.getInstance(true).readAll(PojoUsingListOfObject.class);
2664
Schema pojo = schemas.get("PojoUsingListOfObject");
2765
Assert.assertNotNull(pojo, "PojoUsingListOfObject schema should exist");
@@ -30,10 +68,12 @@ public void listOfObjectItemsShouldBeObjectSchema() {
3068
Schema itemSchema = itemsProp.getItems();
3169
Assert.assertNotNull(itemSchema, "List<Object> items schema should exist");
3270
Assert.assertTrue(isObjectSchema(itemSchema), "Expected List<Object> items to be an object schema in OAS 3.1, but was: type=" + itemSchema.getType() + ", types=" + itemSchema.getTypes() + ", class=" + itemSchema.getClass());
71+
setExplicitTypeObject(null);
3372
}
3473

35-
@Test(description = "OAS 3.1: Map<String,Object> additionalProperties schema should be object")
74+
@Test(description = "OAS 3.1: Map<String,Object> additionalProperties schema should be object if explicit-object-schema is enabled")
3675
public void mapOfObjectAdditionalPropertiesShouldBeObjectSchema() {
76+
setExplicitTypeObject(true);
3777
Map<String, Schema> schemas = ModelConverters.getInstance(true).readAll(PojoUsingMapStringToObject.class);
3878
Schema pojo = schemas.get("PojoUsingMapStringToObject");
3979
Assert.assertNotNull(pojo, "PojoUsingMapStringToObject schema should exist");
@@ -42,6 +82,7 @@ public void mapOfObjectAdditionalPropertiesShouldBeObjectSchema() {
4282
Schema valueSchema = (Schema) additionalProp.getAdditionalProperties();
4383
Assert.assertNotNull(valueSchema, "Map<String,Object> additionalProperties (value schema) should exist");
4484
Assert.assertTrue(isObjectSchema(valueSchema), "Expected Map<String,Object> additionalProperties to be an object schema in OAS 3.1, but was: type=" + valueSchema.getType() + ", types=" + valueSchema.getTypes() + ", class=" + valueSchema.getClass());
85+
setExplicitTypeObject(null);
4586
}
4687

4788
/**
@@ -88,4 +129,10 @@ public void setAdditional(Map<String, Object> additional) {
88129
this.additional = additional;
89130
}
90131
}
132+
133+
// We need to set it programmatically rather than with system properties since the field instantiation is static
134+
// (only read from system env once, thus it cannot be changed/alternated back and forth)
135+
private void setExplicitTypeObject(Boolean value) {
136+
PrimitiveType.explicitObjectType = value;
137+
}
91138
}

modules/swagger-jaxrs2/src/test/java/io/swagger/v3/jaxrs2/ReaderTest.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3596,7 +3596,6 @@ public void testOas31Petstore() {
35963596
" name:\n" +
35973597
" type: string\n" +
35983598
" annotated:\n" +
3599-
" type: object\n" +
36003599
" $ref: \"#/components/schemas/Category\"\n" +
36013600
" description: child description\n" +
36023601
" properties:\n" +
@@ -3650,7 +3649,6 @@ public void test31RefSiblings() {
36503649
" type: object\n" +
36513650
" properties:\n" +
36523651
" annotated:\n" +
3653-
" type: object\n" +
36543652
" $ref: \"#/components/schemas/SimpleCategory\"\n" +
36553653
" description: child description\n" +
36563654
" properties:\n" +
@@ -4113,7 +4111,6 @@ public void testMisc31() {
41134111
" type: object\n" +
41144112
" properties:\n" +
41154113
" country:\n" +
4116-
" type: object\n" +
41174114
" const: United States\n" +
41184115
" CreditCard:\n" +
41194116
" type: object\n" +
@@ -4124,13 +4121,11 @@ public void testMisc31() {
41244121
" type: object\n" +
41254122
" properties:\n" +
41264123
" postalCode:\n" +
4127-
" type: object\n" +
41284124
" pattern: \"[0-9]{5}(-[0-9]{4})?\"\n" +
41294125
" PostalCodePattern:\n" +
41304126
" type: object\n" +
41314127
" properties:\n" +
41324128
" postalCode:\n" +
4133-
" type: object\n" +
41344129
" pattern: \"[A-Z][0-9][A-Z] [0-9][A-Z][0-9]\"\n" +
41354130
" PropertyNamesPattern:\n" +
41364131
" pattern: \"^[A-Za-z_][A-Za-z0-9_]*$\"\n";

modules/swagger-jaxrs2/src/test/resources/petstore/WebHookResource.yaml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,9 @@ webhooks:
2424
$comment: random comment
2525
$id: http://yourdomain.com/schemas/myschema.json
2626
dependentSchemas:
27-
pet:
28-
type: object
27+
pet: {}
2928
patternProperties:
30-
user:
31-
type: object
29+
user: {}
3230
webhook1:
3331
post:
3432
description: "subscribes a client to updates relevant to the requestor's account,\

modules/swagger-jaxrs2/src/test/resources/petstore/callbacks/ComplexCallback31Resource.yaml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,9 @@ paths:
3232
$comment: random comment
3333
$id: http://yourdomain.com/schemas/myschema.json
3434
dependentSchemas:
35-
pet:
36-
type: object
35+
pet: { }
3736
patternProperties:
38-
user:
39-
type: object
37+
user: { }
4038
testCallback2:
4139
http://www.url2.com:
4240
get:

modules/swagger-jaxrs2/src/test/resources/petstore/parameters/Parameters31Resource.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,7 @@ paths:
9696
user:
9797
$ref: "#/components/schemas/User"
9898
properties:
99-
extraObject:
100-
type: object
99+
extraObject: {}
101100
components:
102101
schemas:
103102
Category:

modules/swagger-jaxrs2/src/test/resources/petstore/requestbody/RequestBody31Resource.yaml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,16 @@ paths:
4040
- string
4141
- number
4242
- object
43-
if:
44-
type: object
45-
then:
46-
type: object
47-
else:
48-
type: object
43+
if: {}
44+
then: {}
45+
else: {}
4946
$anchor: parameter $anchor
5047
$schema: parameter $schema
5148
description: User description
5249
example: User Description
5350
exclusiveMaximum: 100
5451
exclusiveMinimum: 1
55-
unevaluatedProperties:
56-
type: object
52+
unevaluatedProperties: {}
5753
required: true
5854
responses:
5955
default:

0 commit comments

Comments
 (0)