Skip to content

Commit 7c63253

Browse files
gracekarinafrantuma
authored andcommitted
oas 3.1 - more Json Schema parsing
1 parent a2fd275 commit 7c63253

File tree

3 files changed

+137
-67
lines changed

3 files changed

+137
-67
lines changed

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java

Lines changed: 7 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ public class OpenAPIDeserializer {
173173
"allOf",
174174
"oneOf", "anyOf", "not", "items", "properties", "additionalProperties", "patternProperties", "description",
175175
"format", "default", "discriminator", "readOnly", "writeOnly", "xml", "externalDocs", "example", "deprecated",
176-
"const"));
176+
"const", "examples", "$id", "$comment"));
177177
protected static Set<String> EXAMPLE_KEYS_31 = new LinkedHashSet<>(Arrays.asList("$ref", "summary", "description",
178178
"value", "externalValue"));
179179
protected static Set<String> HEADER_KEYS_31 = new LinkedHashSet<>(Arrays.asList("$ref", "name", "in", "description",
@@ -572,8 +572,6 @@ public Components getComponents(ObjectNode obj, String location, ParseResult res
572572
validateReservedKeywords(specKeys, key, location, result);
573573

574574
}
575-
576-
577575
return components;
578576
}
579577

@@ -2900,12 +2898,6 @@ at the moment path passed as string (basePath) from upper components can be both
29002898
}
29012899
}
29022900

2903-
2904-
bool = getBoolean("nullable", node, false, location, result);
2905-
if (bool != null) {
2906-
schema.setNullable(bool);
2907-
}
2908-
29092901
bool = getBoolean("readOnly", node, false, location, result);
29102902
if (bool != null) {
29112903
schema.setReadOnly(bool);
@@ -3420,8 +3412,6 @@ public Operation getOperation(ObjectNode obj, String location, ParseResult resul
34203412
}
34213413
validateReservedKeywords(specKeys, key, location, result);
34223414
}
3423-
3424-
34253415
return operation;
34263416
}
34273417

@@ -3558,7 +3548,6 @@ public RequestBody getRequestBody(ObjectNode node, String location, ParseResult
35583548
}
35593549
validateReservedKeywords(specKeys, key, location, result);
35603550
}
3561-
35623551
return body;
35633552
}
35643553

@@ -3852,9 +3841,8 @@ public Schema getJsonSchema(ObjectNode node, String location, ParseResult result
38523841
result.invalidType(location, "required", "string", n);
38533842
}
38543843
}
3855-
if (requiredList.size() > 0) {
3856-
schema.setRequired(requiredList);
3857-
}
3844+
schema.setRequired(requiredList);
3845+
38583846
}
38593847

38603848

@@ -3885,18 +3873,12 @@ public Schema getJsonSchema(ObjectNode node, String location, ParseResult result
38853873
schema.addType(type);
38863874
}
38873875
}
3888-
if (schema.getTypes() != null &&
3889-
schema.getTypes().size() == 1 &&
3890-
"array".equals(schema.getTypes().toArray()[0]) && schema.getItems() == null) {
3891-
result.missing(location, "items");
3892-
}
38933876

38943877
value = getString("format", node, false, location, result);
3895-
if (StringUtils.isNotBlank(value)) {
3878+
if (value != null) {
38963879
schema.setFormat(value);
38973880
}
38983881

3899-
39003882
ArrayNode enumArray = getArray("enum", node, false, location, result);
39013883
if (enumArray != null) {
39023884
for (JsonNode n : enumArray) {
@@ -4089,48 +4071,6 @@ public Schema getJsonSchema(ObjectNode node, String location, ParseResult result
40894071
schema.setDescription(value);
40904072
}
40914073

4092-
//sets default value according to the schema type
4093-
if (node.get("default") != null) {
4094-
if (!StringUtils.isBlank(schema.getType())) {
4095-
if (schema.getType().equals("array")) {
4096-
ArrayNode array = getArray("default", node, false, location, result);
4097-
if (array != null) {
4098-
schema.setDefault(array);
4099-
}
4100-
} else if (schema.getType().equals("string")) {
4101-
value = getString("default", node, false, location, result);
4102-
if (value != null) {
4103-
try {
4104-
schema.setDefault(getDecodedObject(schema, value));
4105-
} catch (ParseException e) {
4106-
result.invalidType(location, String.format("default=`%s`", e.getMessage()),
4107-
schema.getFormat(), node);
4108-
}
4109-
}
4110-
} else if (schema.getType().equals("boolean")) {
4111-
bool = getBoolean("default", node, false, location, result);
4112-
if (bool != null) {
4113-
schema.setDefault(bool);
4114-
}
4115-
} else if (schema.getType().equals("object")) {
4116-
Object object = getObject("default", node, false, location, result);
4117-
if (object != null) {
4118-
schema.setDefault(object);
4119-
}
4120-
} else if (schema.getType().equals("integer")) {
4121-
Integer number = getInteger("default", node, false, location, result);
4122-
if (number != null) {
4123-
schema.setDefault(number);
4124-
}
4125-
} else if (schema.getType().equals("number")) {
4126-
BigDecimal number = getBigDecimal("default", node, false, location, result);
4127-
if (number != null) {
4128-
schema.setDefault(number);
4129-
}
4130-
}
4131-
}
4132-
}
4133-
41344074
//const is a String
41354075
value = getString("const", node, false, location, result);
41364076
if (value != null) {
@@ -4228,13 +4168,13 @@ public Schema getJsonSchema(ObjectNode node, String location, ParseResult result
42284168
Set<String> schemaKeys = getKeys(node);
42294169
Map<String, Set<String>> specKeys = KEYS.get("openapi31");
42304170
for (String key : schemaKeys) {
4171+
validateReservedKeywords(specKeys, key, location, result);
42314172
if (!specKeys.get("SCHEMA_KEYS").contains(key) && !key.startsWith("x-")) {
4232-
result.extra(location, key, node.get(key));
4173+
extensions.put(key, Json.mapper().convertValue(node.get(key), Object.class));
4174+
schema.setExtensions(extensions);
42334175
}
42344176
}
4235-
42364177
return schema;
4237-
42384178
}
42394179

42404180
public static class ParseResult {

modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OAI31DeserializationTest.java

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.swagger.v3.parser.test;
22

3+
import io.swagger.v3.core.util.Yaml;
34
import io.swagger.v3.core.util.Yaml31;
45
import io.swagger.v3.oas.models.OpenAPI;
56
import io.swagger.v3.oas.models.media.Schema;
@@ -597,4 +598,132 @@ public void testExamplesJSONSchema() {
597598
Schema exampleSchema = openAPI.getComponents().getSchemas().get("ExampleSchema");
598599
assertTrue(exampleSchema.getExample().equals("foo"));
599600
}
601+
602+
@Test(description = "Test arbitraryKeywords in JSONSchema")
603+
public void testArbitraryKeywordsJSONSchema() {
604+
ParseOptions options = new ParseOptions();
605+
String arbitraryKeyword = "openapi: 3.1.0\n" +
606+
"info:\n" +
607+
" title: arbitrary keywords JSONSchema\n" +
608+
" version: 1.0.0\n" +
609+
"servers:\n" +
610+
" - url: /\n" +
611+
"paths: { }\n" +
612+
"components:\n" +
613+
" schemas:\n" +
614+
" Fruit:\n" +
615+
" type: string\n" +
616+
" example: kiwi\n" +
617+
" examples:\n" +
618+
" - apple\n" +
619+
" - orange\n" +
620+
" arbitraryKeyword: test\n" +
621+
" x-normalExtension: extensionTest\n";
622+
SwaggerParseResult result = new OpenAPIV3Parser().readContents( arbitraryKeyword , null, options);
623+
OpenAPI openAPI = result.getOpenAPI();
624+
assertNotNull(openAPI);
625+
assertNotNull(openAPI.getComponents().getSchemas().get("Fruit").getExtensions().get("arbitraryKeyword"));
626+
assertNotNull(openAPI.getComponents().getSchemas().get("Fruit").getExtensions().get("x-normalExtension"));
627+
}
628+
629+
@Test(description = "Test for Tuple parsing")
630+
public void testTuplesJSONSchema() {
631+
ParseOptions options = new ParseOptions();
632+
String tuple = "openapi: 3.1.0\n" +
633+
"info:\n" +
634+
" title: tuple JSONSchema\n" +
635+
" version: 1.0.0\n" +
636+
"servers:\n" +
637+
" - url: /\n" +
638+
"paths: { }\n" +
639+
"components:\n" +
640+
" schemas:\n" +
641+
" Tuple:\n" +
642+
" type: array\n" +
643+
" prefixItems:\n" +
644+
" - type: string\n" +
645+
" description: Name\n" +
646+
" - type: integer\n" +
647+
" description: Age\n" +
648+
" minItems: 2\n" +
649+
" maxItems: 2\n";
650+
SwaggerParseResult result = new OpenAPIV3Parser().readContents(tuple, null, options);
651+
OpenAPI openAPI = result.getOpenAPI();
652+
assertNotNull(openAPI);
653+
assertTrue(openAPI.getComponents().getSchemas().get("Tuple").getPrefixItems().get(0) instanceof Schema);
654+
Schema schema = (Schema) openAPI.getComponents().getSchemas().get("Tuple").getPrefixItems().get(0);
655+
assertTrue(schema.getTypes().contains("string"));
656+
assertEquals(schema.getDescription(), "Name");
657+
}
658+
659+
@Test(description = "Test for not setting the schema type as default")
660+
public void testNotDefaultSchemaType() {
661+
ParseOptions options = new ParseOptions();
662+
String defaultSchemaType = "openapi: 3.1.0\n" +
663+
"info:\n" +
664+
" title: ping test\n" +
665+
" version: '1.0'\n" +
666+
"servers:\n" +
667+
" - url: 'http://localhost:8000/'\n" +
668+
"paths:\n" +
669+
" /ping:\n" +
670+
" get:\n" +
671+
" operationId: pingGet\n" +
672+
" responses:\n" +
673+
" '201':\n" +
674+
" description: OK\n" +
675+
"components:\n" +
676+
" schemas:\n" +
677+
" AnyValue: {}\n" +
678+
" AnyValueWithDesc:\n" +
679+
" description: Can be any value - string, number, boolean, array or object.\n" +
680+
" AnyValueNullable:\n" +
681+
" nullable: true\n" +
682+
" description: Can be any value, including `null`.\n" +
683+
" AnyValueModel:\n" +
684+
" description: test any value\n" +
685+
" type: object\n" +
686+
" properties:\n" +
687+
" any_value:\n" +
688+
" $ref: '#/components/schemas/AnyValue'\n" +
689+
" any_value_with_desc:\n" +
690+
" $ref: '#/components/schemas/AnyValueWithDesc'\n" +
691+
" any_value_nullable:\n" +
692+
" $ref: '#/components/schemas/AnyValueNullable'\n" +
693+
" AnyValueModelInline:\n" +
694+
" description: test any value inline\n" +
695+
" type: object\n" +
696+
" properties:\n" +
697+
" any_value: {}\n" +
698+
" any_value_with_desc:\n" +
699+
" description: inline any value\n" +
700+
" any_value_nullable:\n" +
701+
" nullable: true\n" +
702+
" description: inline any value nullable\n" +
703+
" map_any_value:\n" +
704+
" additionalProperties: {}\n" +
705+
" map_any_value_with_desc:\n" +
706+
" additionalProperties: \n" +
707+
" description: inline any value\n" +
708+
" map_any_value_nullable:\n" +
709+
" additionalProperties:\n" +
710+
" nullable: true\n" +
711+
" description: inline any value nullable\n" +
712+
" array_any_value:\n" +
713+
" items: {}\n" +
714+
" array_any_value_with_desc:\n" +
715+
" items: \n" +
716+
" description: inline any value\n" +
717+
" array_any_value_nullable:\n" +
718+
" items:\n" +
719+
" nullable: true\n" +
720+
" description: inline any value nullable";
721+
SwaggerParseResult result = new OpenAPIV3Parser().readContents(defaultSchemaType, null, options);
722+
OpenAPI openAPI = result.getOpenAPI();
723+
assertNotNull(openAPI);
724+
assertNotNull(openAPI.getComponents().getSchemas().get("AnyValueModelInline").getProperties().get("map_any_value"));
725+
assertTrue(openAPI.getComponents().getSchemas().get("AnyValueModelInline").getProperties().get("map_any_value") instanceof Schema);
726+
Schema mapProperty = (Schema)openAPI.getComponents().getSchemas().get("AnyValueModelInline").getProperties().get("map_any_value");
727+
assertNull(mapProperty.getType());
728+
}
600729
}

modules/swagger-parser-v3/src/test/resources/3.1.0/basic.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ components:
135135
const: pending
136136
tag:
137137
type: string
138+
arbitraryKeyword: test
138139
Pets:
139140
type: array
140141
items:

0 commit comments

Comments
 (0)