package io.swagger.parser.util; import io.swagger.models.*; import io.swagger.models.auth.ApiKeyAuthDefinition; import io.swagger.models.auth.BasicAuthDefinition; import io.swagger.models.auth.In; import io.swagger.models.auth.SecuritySchemeDefinition; import io.swagger.models.parameters.BodyParameter; import io.swagger.models.parameters.Parameter; import io.swagger.models.parameters.QueryParameter; import io.swagger.models.properties.*; import io.swagger.parser.SwaggerParser; import io.swagger.parser.SwaggerResolver; import io.swagger.util.Json; import org.testng.Assert; import org.testng.annotations.Test; import java.math.BigDecimal; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import static org.junit.Assert.*; public class SwaggerDeserializerTest { @Test public void testSecurityDeserialization() throws Exception { String json = "{\n" + " \"swagger\": \"2.0\",\n" + " \"security\": [\n" + " {\n" + " \"api_key1\": [],\n" + " \"api_key2\": []\n" + " },\n" + " {\n" + " \"api_key3\": []\n" + " }\n" + " ]\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); List<String> messageList = result.getMessages(); Set<String> messages = new HashSet<String>(messageList); Swagger swagger = result.getSwagger(); assertNotNull(swagger); List<SecurityRequirement> security = swagger.getSecurity(); assertTrue(security.size() == 2); } @Test public void testSchema() throws Exception { String json = "{\n" + " \"type\":\"object\",\n" + " \"properties\": {\n" + " \"data\": {\n" + " \"properties\": {\n" + " \"name\": {\n" + " \"type\": \"string\",\n" + " \"minLength\": 1\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"required\": [\n" + " \"data\"\n" + " ]\n" + "}"; Model m = Json.mapper().readValue(json, Model.class); assertNotNull(m); Map<String, Property> properties = m.getProperties(); assertTrue(properties.keySet().size() == 1); Property data = properties.get("data"); assertTrue(data instanceof ObjectProperty); ObjectProperty op = (ObjectProperty) data; Map<String, Property> innerProperties = ((ObjectProperty) data).getProperties(); assertTrue(innerProperties.keySet().size() == 1); Property name = innerProperties.get("name"); assertTrue(name instanceof StringProperty); } @Test public void testArraySchema() throws Exception { String json = "{\n" + " \"properties\": {\n" + " \"data\": {\n" + " \"properties\": {\n" + " \"description\": \"the array type\",\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"properties\": {\n" + " \"name\": {\n" + " \"description\": \"the inner type\",\n" + " \"type\": \"string\",\n" + " \"minLength\": 1\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"required\": [\n" + " \"data\"\n" + " ]\n" + "}"; Model m = Json.mapper().readValue(json, Model.class); Property data = m.getProperties().get("data"); assertTrue(data instanceof ArrayProperty); ArrayProperty ap = (ArrayProperty) data; assertEquals("the array type", ap.getDescription()); Property inner = ap.getItems(); assertNotNull(inner); assertTrue(inner instanceof ObjectProperty); ObjectProperty op = (ObjectProperty) inner; Property name = op.getProperties().get("name"); assertEquals(name.getDescription(), "the inner type"); assertTrue(((StringProperty)name).getMinLength() == 1); } @Test public void testEmpty() { String json = "{}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); List<String> messageList = result.getMessages(); Set<String> messages = new HashSet<String>(messageList); assertTrue(messages.contains("attribute swagger is missing")); assertTrue(messages.contains("attribute info is missing")); assertTrue(messages.contains("attribute paths is missing")); } @Test public void testSecurity() { String json = "{\n" + " \"swagger\": \"2.0\",\n" + " \"security\": [\n" + " {\n" + " \"petstore_auth\": [\n" + " \"write:pets\",\n" + " \"read:pets\"\n" + " ]\n" + " }\n" + " ]\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); List<String> messageList = result.getMessages(); Set<String> messages = new HashSet<String>(messageList); Swagger swagger = result.getSwagger(); assertNotNull(swagger.getSecurity()); List<SecurityRequirement> security = swagger.getSecurity(); Assert.assertTrue(security.size() == 1); Assert.assertTrue(security.get(0).getRequirements().size() == 1); List<String> requirement = security.get(0).getRequirements().get("petstore_auth"); Assert.assertTrue(requirement.size() == 2); Set<String> requirements = new HashSet(requirement); Assert.assertTrue(requirements.contains("read:pets")); Assert.assertTrue(requirements.contains("write:pets")); } @Test public void testSecurityDefinition() { String json = "{\n" + " \"swagger\": \"2.0\",\n" + " \"securityDefinitions\": {\n" + " \"basic_auth\": {\n" + " \"type\": \"basic\",\n" + " \"x-foo\": \"basicBar\"\n" + " },\n" + " \"api_key\": {\n" + " \"type\": \"apiKey\",\n" + " \"name\": \"api_key\",\n" + " \"in\": \"header\",\n" + " \"description\": \"api key description\",\n" + " \"x-foo\": \"apiKeyBar\"\n" + " }\n" + " },\n" + " \"paths\": {\n" + " \"/pet\": {\n" + " \"get\": {\n" + " \"security\": [\n" + " {\n" + " \"basic_auth\": [],\n" + " \"api_key\": []\n" + " }\n" + " ]\n" + " }\n" + " }\n" + " }\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); List<String> messageList = result.getMessages(); Set<String> messages = new HashSet<String>(messageList); Swagger swagger = result.getSwagger(); assertNotNull(swagger.getSecurityDefinitions()); assertTrue(swagger.getSecurityDefinitions().keySet().size() == 2); // Basic Authentication SecuritySchemeDefinition definitionBasic = swagger.getSecurityDefinitions().get("basic_auth"); assertNotNull(definitionBasic); assertTrue(definitionBasic instanceof BasicAuthDefinition); assertEquals(definitionBasic.getVendorExtensions().get("x-foo"), "basicBar"); // API Key Authentication SecuritySchemeDefinition definition = swagger.getSecurityDefinitions().get("api_key"); assertNotNull(definition); assertTrue(definition instanceof ApiKeyAuthDefinition); ApiKeyAuthDefinition apiKey = (ApiKeyAuthDefinition) definition; assertEquals(apiKey.getName(), "api_key"); assertEquals(apiKey.getIn(), In.HEADER); assertEquals(apiKey.getDescription(), "api key description"); assertEquals(apiKey.getVendorExtensions().get("x-foo"), "apiKeyBar"); } @Test public void testSecurityDefinitionWithMissingAttribute() { String json = "{\n" + " \"swagger\": \"2.0\",\n" + " \"securityDefinitions\": {\n" + " \"api_key\": {\n" + " \"description\": \"api key description\"\n" + " }\n" + " }\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); List<String> messageList = result.getMessages(); Set<String> messages = new HashSet<>(messageList); assertTrue(messages.contains("attribute securityDefinitions.api_key.type is missing")); } @Test public void testRootInfo() { String json = "{\n" + "\t\"swagger\": \"2.0\",\n" + "\t\"foo\": \"bar\",\n" + "\t\"info\": \"invalid\"\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); List<String> messageList = result.getMessages(); Set<String> messages = new HashSet<String>(messageList); assertTrue(messages.contains("attribute foo is unexpected")); assertTrue(messages.contains("attribute info is not of type `object`")); } @Test public void testContact() { String json = "{\n" + "\t\"swagger\": \"2.0\",\n" + "\t\"info\": {\n" + "\t\t\"title\": \"title\",\n" + "\t\t\"bad\": \"bad\",\n" + "\t\t\"x-foo\": \"bar\",\n" + "\t\t\"description\": \"description\",\n" + "\t\t\"termsOfService\": \"tos\",\n" + "\t\t\"contact\": {\n" + "\t\t\t\"name\": \"tony\",\n" + "\t\t\t\"url\": \"url\",\n" + "\t\t\t\"email\": \"email\",\n" + "\t\t\t\"invalid\": \"invalid\",\n" + "\t\t\t\"x-fun\": true\n" + "\t\t},\n" + "\t\t\"version\": \"version\"\n" + "\t}\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); List<String> messageList = result.getMessages(); Set<String> messages = new HashSet<String>(messageList); assertEquals(result.getSwagger().getInfo().getTitle(), "title"); assertEquals(result.getSwagger().getInfo().getDescription(), "description"); assertEquals(result.getSwagger().getInfo().getTermsOfService(), "tos"); assertEquals(result.getSwagger().getInfo().getVersion(), "version"); Contact contact = result.getSwagger().getInfo().getContact(); assertEquals(contact.getName(), "tony"); assertEquals(contact.getUrl(), "url"); assertEquals(contact.getEmail(), "email"); assertTrue(messages.contains("attribute info.contact.x-fun is unexpected")); assertTrue(messages.contains("attribute info.bad is unexpected")); assertTrue(messages.contains("attribute info.contact.invalid is unexpected")); assertEquals(result.getSwagger().getInfo().getVendorExtensions().get("x-foo").toString(), "bar"); } @Test public void testResponses() { String json = "{\n" + "\t\"swagger\": \"2.0\",\n" + "\t\"responses\": {\n" + "\t\t\"foo\": {\n" + "\t\t\t\"description\": \"description\",\n" + "\t\t\t\"bar\": \"baz\",\n" + "\t\t\t\"x-foo\": \"bar\"\n" + "\t\t}\n" + "\t}\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); List<String> messageList = result.getMessages(); Set<String> messages = new HashSet<String>(messageList); assertTrue(messages.contains("attribute responses.foo.bar is unexpected")); assertEquals(result.getSwagger().getResponses().get("foo").getVendorExtensions().get("x-foo").toString(), "bar"); } @Test public void testLicense () { String json = "{\n" + "\t\"swagger\": \"2.0\",\n" + "\t\"info\": {\n" + "\t\t\"license\": {\n" + "\t\t\t\"invalid\": true,\n" + "\t\t\t\"x-valid\": {\n" + "\t\t\t\t\"isValid\": true\n" + "\t\t\t}\n" + "\t\t}\n" + "\t}\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); List<String> messageList = result.getMessages(); Set<String> messages = new HashSet<String>(messageList); assertTrue(messages.contains("attribute info.license.invalid is unexpected")); assertTrue(messages.contains("attribute info.title is missing")); assertTrue(messages.contains("attribute paths is missing")); assertEquals(((Map)result.getSwagger().getInfo().getLicense().getVendorExtensions().get("x-valid")).get("isValid"), true); } @Test public void testDefinitions () { String json = "{\n" + " \"swagger\": \"2.0\",\n" + " \"definitions\": {\n" + " \"invalid\": true,\n" + " \"Person\": {\n" + " \"required\": [\n" + " \"id\",\n" + " \"name\"\n" + " ],\n" + " \"properties\": {\n" + " \"id\": {\n" + " \"type\": \"integer\",\n" + " \"format\": \"int64\"\n" + " },\n" + " \"name\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); List<String> messageList = result.getMessages(); Set<String> messages = new HashSet<String>(messageList); assertTrue(messages.contains("attribute definitions.invalid is not of type `object`")); assertTrue(result.getSwagger().getDefinitions().get("Person") instanceof ModelImpl); List<String> required = ((ModelImpl)result.getSwagger().getDefinitions().get("Person")).getRequired(); Set<String> requiredKeys = new HashSet<String>(required); assertTrue(requiredKeys.contains("id")); assertTrue(requiredKeys.contains("name")); assertTrue(requiredKeys.size() == 2); } @Test public void testNestedDefinitions() { String json = "{\n" + " \"swagger\": \"2.0\",\n" + " \"definitions\": {\n" + " \"Person\": {\n" + " \"required\": [\n" + " \"id\",\n" + " \"name\"\n" + " ],\n" + " \"properties\": {\n" + " \"id\": {\n" + " \"type\": \"integer\",\n" + " \"format\": \"int64\"\n" + " },\n" + " \"name\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"address\": {\n" + " \t\"$ref\": \"#/definitions/Address\"\n" + " }\n" + " }\n" + " },\n" + " \"Address\": {\n" + " \t\"required\": [\"zip\"],\n" + " \t\"properties\": {\n" + " \t\t\"street\": {\n" + " \t\t\t\"type\": \"string\"\n" + " \t\t},\n" + " \t\t\"zip\": {\n" + " \t\t\t\"type\": \"integer\",\n" + " \t\t\t\"format\": \"int32\",\n" + " \t\t\t\"minimum\": 0,\n" + " \t\t\t\"exclusiveMinimum\": true,\n" + " \t\t\t\"maximum\": 99999,\n" + " \t\t\t\"exclusiveMaximum\": true\n" + " \t\t}\n" + " \t}\n" + " }\n" + " }\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); List<String> messageList = result.getMessages(); Set<String> messages = new HashSet<String>(messageList); assertTrue(result.getSwagger().getDefinitions().get("Person") instanceof ModelImpl); assertTrue(result.getSwagger().getDefinitions().get("Address") instanceof ModelImpl); ModelImpl person = (ModelImpl) result.getSwagger().getDefinitions().get("Person"); Property property = person.getProperties().get("address"); assertTrue(property instanceof RefProperty); Property zip = ((ModelImpl)result.getSwagger().getDefinitions().get("Address")).getProperties().get("zip"); assertTrue(zip instanceof IntegerProperty); IntegerProperty zipProperty = (IntegerProperty) zip; assertEquals(zipProperty.getMinimum(), new BigDecimal("0")); assertTrue(zipProperty.getExclusiveMinimum()); assertEquals(zipProperty.getMaximum(), new BigDecimal("99999")); assertTrue(zipProperty.getExclusiveMaximum()); } @Test public void testPaths() { String json = "{\n" + " \"swagger\": \"2.0\",\n" + " \"paths\": {\n" + " \"/pet\": {\n" + " \"foo\": \"bar\",\n" + " \"get\": {\n" + " \"security\": [\n" + " {\n" + " \"petstore_auth\": [\n" + " \"write:pets\",\n" + " \"read:pets\"\n" + " ]\n" + " }\n" + " ]\n" + " }\n" + " }\n" + " }\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); List<String> messageList = result.getMessages(); Set<String> messages = new HashSet<String>(messageList); assertTrue(messages.contains("attribute paths.'/pet'.foo is unexpected")); Swagger swagger = result.getSwagger(); Path path = swagger.getPath("/pet"); assertNotNull(path); Operation operation = path.getGet(); assertNotNull(operation); List<Map<String, List<String>>> security = operation.getSecurity(); assertTrue(security.size() == 1); Map<String, List<String>> requirement = security.get(0); assertTrue(requirement.containsKey("petstore_auth")); List<String> scopesList = requirement.get("petstore_auth"); Set<String> scopes = new HashSet<String>(scopesList); assertTrue(scopes.contains("read:pets")); assertTrue(scopes.contains("write:pets")); } @Test public void testPathsWithRefResponse() { String json = "{\n" + " \"swagger\": \"2.0\",\n" + " \"paths\": {\n" + " \"/pet\": {\n" + " \"get\": {\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"$ref\": \"#/responses/OK\"" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); Swagger swagger = result.getSwagger(); Path path = swagger.getPath("/pet"); assertNotNull(path); Operation operation = path.getGet(); assertNotNull(operation); assertTrue(operation.getResponses().containsKey("200")); assertEquals(RefResponse.class,operation.getResponses().get("200").getClass()); RefResponse refResponse = (RefResponse)operation.getResponses().get("200"); assertEquals("#/responses/OK",refResponse.get$ref()); } @Test public void testArrayModelDefinition() { String json = "{\n" + " \"paths\": {\n" + " \"/store/inventory\": {\n" + " \"get\": {\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"description\": \"successful operation\",\n" + " \"schema\": {\n" + " \"type\": \"object\",\n" + " \"additionalProperties\": {\n" + " \"type\": \"integer\",\n" + " \"format\": \"int32\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); List<String> messageList = result.getMessages(); Set<String> messages = new HashSet<String>(messageList); Swagger swagger = result.getSwagger(); Property response = swagger.getPath("/store/inventory").getGet().getResponses().get("200").getSchema(); assertTrue(response instanceof MapProperty); } @Test public void testArrayQueryParam() throws Exception { String json = "{\n" + " \"swagger\": \"2.0\",\n" + " \"paths\": {\n" + " \"/pet/findByStatus\": {\n" + " \"get\": {\n" + " \"parameters\": [\n" + " {\n" + " \"name\": \"status\",\n" + " \"in\": \"query\",\n" + " \"description\": \"Status values that need to be considered for filter\",\n" + " \"required\": false,\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"collectionFormat\": \"pipes\",\n" + " \"default\": \"available\"\n" + " }\n" + " ],\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"description\": \"successful operation\",\n" + " \"schema\": {\n" + " \"$ref\": \"#/definitions/PetArray\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); Swagger swagger = result.getSwagger(); Parameter param = swagger.getPath("/pet/findByStatus").getGet().getParameters().get(0); assertTrue(param instanceof QueryParameter); QueryParameter qp = (QueryParameter) param; Property p = qp.getItems(); assertEquals(qp.getType(), "array"); assertTrue(p instanceof StringProperty); } @Test(description = "it should read a top-level extension per https://github.com/swagger-api/validator-badge/issues/59") public void testToplevelExtension() throws Exception { String json = "\n" + "{\n" + " \"swagger\": \"2.0\",\n" + "\t\"x-foo\" : \"woof\",\n" + " \"info\": {\n" + " \"version\": \"0.0.0\",\n" + " \"title\": \"Simple API\"\n" + " },\n" + " \"paths\": {\n" + " \"/\": {\n" + " \"get\": {\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"description\": \"OK\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); } @Test public void testDeserializeBinaryString() { String json = "{\n" + " \"swagger\": \"2.0\",\n" + " \"info\": {\n" + " \"title\": \"foo\"\n" + " },\n" + " \"paths\": {\n" + " \"/test\": {\n" + " \"post\": {\n" + " \"parameters\": [\n" + " {\n" + " \"name\": \"AnyName\",\n" + " \"in\": \"body\",\n" + " \"schema\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"binary\"\n" + " }\n" + " }\n" + " ],\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"description\": \"ok\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); final Swagger resolved = new SwaggerResolver(result.getSwagger(), null).resolve(); } @Test public void testDeserializeEnum() { String yaml = "swagger: '2.0'\n" + "info:\n" + " version: 0.0.0\n" + " title: your title\n" + "paths:\n" + " /persons:\n" + " get:\n" + " description: a test\n" + " responses:\n" + " '200':\n" + " description: Successful response\n" + " schema:\n" + " type: object\n" + " properties:\n" + " se:\n" + " $ref: '#/definitions/StringEnum'\n" + " ie:\n" + " $ref: '#/definitions/IntegerEnum'\n" + " ne:\n" + " $ref: '#/definitions/NumberEnum'\n" + "definitions:\n" + " StringEnum:\n" + " type: string\n" + " default: foo\n" + " enum:\n" + " - First\n" + " - Second\n" + " IntegerEnum:\n" + " type: integer\n" + " default: 1\n" + " enum:\n" + " - -1\n" + " - 0\n" + " - 1\n" + " NumberEnum:\n" + " type: number\n" + " default: 3.14\n" + " enum:\n" + " - -1.151\n" + " - 0.0\n" + " - 1.6161\n" + " - 3.14"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(yaml); final Swagger resolved = new SwaggerResolver(result.getSwagger(), null).resolve(); Model stringModel = resolved.getDefinitions().get("StringEnum"); assertTrue(stringModel instanceof ModelImpl); ModelImpl stringImpl = (ModelImpl) stringModel; List<String> stringValues = stringImpl.getEnum(); assertEquals(2, stringValues.size()); assertEquals("First", stringValues.get(0)); assertEquals("Second", stringValues.get(1)); Model integerModel = resolved.getDefinitions().get("IntegerEnum"); assertTrue(integerModel instanceof ModelImpl); ModelImpl integerImpl = (ModelImpl) integerModel; List<String> integerValues = integerImpl.getEnum(); assertEquals(3, integerValues.size()); assertEquals("-1", integerValues.get(0)); assertEquals("0", integerValues.get(1)); assertEquals("1", integerValues.get(2)); Model numberModel = resolved.getDefinitions().get("NumberEnum"); assertTrue(numberModel instanceof ModelImpl); ModelImpl numberImpl = (ModelImpl) numberModel; List<String> numberValues = numberImpl.getEnum(); assertEquals(4, numberValues.size()); assertEquals("-1.151", numberValues.get(0)); assertEquals("0.0", numberValues.get(1)); assertEquals("1.6161", numberValues.get(2)); assertEquals("3.14", numberValues.get(3)); } @Test public void testDeserializeWithMessages() { String yaml = "swagger: '2.0'\n" + "info:\n" + " version: 0.0.0\n" + " title:\n" + " - bar"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(yaml); Set<String> messages = new HashSet<String>(result.getMessages()); assertTrue(messages.size() == 2); assertTrue(messages.contains("attribute info.title is not of type `string`")); assertTrue(messages.contains("attribute paths is missing")); } @Test public void testDeserializeWithDiscriminator() { String yaml = "swagger: '2.0'\n" + "definitions: \n" + " Animal:\n" + " type: object\n" + " discriminator: petType\n" + " description: |\n" + " A basic `Animal` object which can extend to other animal types.\n" + " required:\n" + " - commonName\n" + " - petType\n" + " properties:\n" + " commonName:\n" + " description: the household name of the animal\n" + " type: string\n" + " petType:\n" + " description: |\n" + " The discriminator for the animal type. It _must_\n" + " match one of the concrete schemas by name (i.e. `Cat`)\n" + " for proper deserialization\n" + " type: string"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(yaml); Set<String> messages = new HashSet<String>(result.getMessages()); assertFalse(messages.contains("attribute definitions.Animal.discriminator is unexpected")); } @Test public void testDeserializeWithEnumDiscriminator() { String yaml = "swagger: '2.0'\n" + "definitions: \n" + " Animal:\n" + " type: object\n" + " discriminator: petType\n" + " description: |\n" + " A basic `Animal` object which can extend to other animal types.\n" + " required:\n" + " - commonName\n" + " - petType\n" + " properties:\n" + " commonName:\n" + " description: the household name of the animal\n" + " type: string\n" + " petType:\n" + " description: |\n" + " The discriminator for the animal type. It _must_\n" + " match one of the concrete schemas by name (i.e. `Cat`)\n" + " for proper deserialization\n" + " enum:\n" + " - cat\n" + " - dog"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(yaml); Map<String, Property> properties = result.getSwagger().getDefinitions().get("Animal").getProperties(); assertTrue(properties.containsKey("commonName")); assertTrue(properties.containsKey("petType")); assertEquals(properties.get("petType").getType(), "string"); } @Test public void testDeserializeWithNumericEnumDiscriminator() { String yaml = "swagger: '2.0'\n" + "definitions: \n" + " Animal:\n" + " type: object\n" + " discriminator: petType\n" + " description: |\n" + " A basic `Animal` object which can extend to other animal types.\n" + " required:\n" + " - commonName\n" + " - petType\n" + " properties:\n" + " commonName:\n" + " description: the household name of the animal\n" + " type: string\n" + " petType:\n" + " enum:\n" + " - 1\n" + " - 2"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(yaml); Map<String, Property> properties = result.getSwagger().getDefinitions().get("Animal").getProperties(); assertTrue(properties.containsKey("commonName")); assertTrue(properties.containsKey("petType")); assertEquals(properties.get("petType").getType(), "number"); } @Test public void testDeserializeWithBooleanEnumDiscriminator() { String yaml = "swagger: '2.0'\n" + "definitions: \n" + " Animal:\n" + " type: object\n" + " discriminator: petType\n" + " description: |\n" + " A basic `Animal` object which can extend to other animal types.\n" + " required:\n" + " - commonName\n" + " - petType\n" + " properties:\n" + " commonName:\n" + " description: the household name of the animal\n" + " type: string\n" + " petType:\n" + " enum:\n" + " - true\n" + " - false"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(yaml); Map<String, Property> properties = result.getSwagger().getDefinitions().get("Animal").getProperties(); assertTrue(properties.containsKey("commonName")); assertTrue(properties.containsKey("petType")); assertEquals(properties.get("petType").getType(), "boolean"); } @Test public void testIssue161() { String yaml = "swagger: '2.0'\n" + "paths:\n" + " /users:\n" + " get:\n" + " parameters:\n" + " - in: query\n" + " name: name\n" + " type: string\n" + " minLength: 10\n" + " maxLength: 100\n" + " required: false\n" + " responses:\n" + " default:\n" + " description: ok"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(yaml); Set<String> messages = new HashSet<String>(result.getMessages()); assertFalse(messages.contains("attribute paths.'/users'(get).[name].maxLength is unexpected")); } @Test public void testValidatorIssue50() { String json = "{\n" + " \"swagger\": \"2.0\",\n" + " \"info\": {\n" + " \"version\": \"2.0.0\",\n" + " \"title\": \"Beanhunter API\",\n" + " \"description\": \"Description of the api goes here.\"\n" + " },\n" + " \"host\": \"local.xxx.com\",\n" + " \"schemes\": [\n" + " \"http\"\n" + " ],\n" + " \"consumes\": [\n" + " \"application/json\"\n" + " ],\n" + " \"produces\": [\n" + " \"application/json\"\n" + " ],\n" + " \"paths\": {\n" + " \"/city\": {\n" + " \"get\": {\n" + " \"description\": \"test description\",\n" + " \"responses\": {}\n" + " }\n" + " }\n" + " },\n" + " \"definitions\": {\n" + " \"Endpoints\": {\n" + " \"title\": \"Endpoints object\",\n" + " \"properties\": {\n" + " \"links\": {}\n" + " }\n" + " }\n" + " }\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); assertTrue(result.getMessages().size() == 1); } @Test public void testIssue151() throws Exception { String json = "{\n" + " \"swagger\": \"2.0\",\n" + " \"info\": {\n" + " \"version\": \"2.0.0\",\n" + " \"title\": \"Test Issue 151\",\n" + " \"description\": \"Tests that ComposedModel vendor extensions are deserialized correctly.\"\n" + " },\n" + " \"paths\": {\n" + " \"/\": {\n" + " \"get\": {\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"description\": \"OK\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"definitions\": {\n" + " \"Pet\": {\n" + " \"type\": \"object\",\n" + " \"required\": [\n" + " \"id\"\n" + " ],\n" + " \"properties\": {\n" + " \"id\": {\n" + " \"type\": \"integer\",\n" + " \"format\": \"int64\"\n" + " }\n" + " }\n" + " },\n" + " \"Dog\": {\n" + " \"type\": \"object\",\n" + " \"allOf\": [\n" + " {\n" + " \"$ref\": \"#/definitions/Pet\"\n" + " },\n" + " {\n" + " \"required\": [\n" + " \"name\"\n" + " ],\n" + " \"properties\": {\n" + " \"name\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " }\n" + " ],\n" + " \"x-vendor-ext\": \"some data\"\n" + " }\n" + " }\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); assertTrue("Parser returned errors:", result.getMessages().isEmpty()); Swagger swagger = result.getSwagger(); Map<String, Model> definitions = swagger.getDefinitions(); assertTrue(definitions.size() == 2); Model allOfModel = definitions.get("Dog"); assertTrue(allOfModel instanceof ComposedModel); assertFalse(allOfModel.getVendorExtensions().isEmpty()); assertEquals("some data", allOfModel.getVendorExtensions().get("x-vendor-ext")); } @Test public void testIssue204_allOf() throws Exception { String json = "{\n" + " \"swagger\": \"2.0\",\n" + " \"info\": {\n" + " \"version\": \"2.0.0\",\n" + " \"title\": \"Test allOf API\",\n" + " \"description\": \"Tests the allOf API for parent, interface and child models.\"\n" + " },\n" + " \"paths\": {\n" + " \"/\": {\n" + " \"get\": {\n" + " \"responses\": {\n" + " \"200\": {\n" + " \"description\": \"OK\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"definitions\": {\n" + " \"Pet\": {\n" + " \"type\": \"object\",\n" + " \"required\": [\n" + " \"id\"\n" + " ],\n" + " \"properties\": {\n" + " \"id\": {\n" + " \"type\": \"integer\",\n" + " \"format\": \"int64\"\n" + " }\n" + " }\n" + " },\n" + " \"Furry\": {\n" + " \"type\": \"object\",\n" + " \"required\": [\n" + " \"coatColour\"\n" + " ],\n" + " \"properties\": {\n" + " \"coatColour\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " },\n" + " \"Dog\": {\n" + " \"type\": \"object\",\n" + " \"allOf\": [\n" + " {\n" + " \"$ref\": \"#/definitions/Pet\"\n" + " },\n" + " {\n" + " \"$ref\": \"#/definitions/Furry\"\n" + " },\n" + " {\n" + " \"required\": [\n" + " \"name\"\n" + " ],\n" + " \"properties\": {\n" + " \"name\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " }\n" + " ]\n" + " }\n" + " }\n" + "}"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); assertTrue("Parser returned errors:", result.getMessages().isEmpty()); Swagger swagger = result.getSwagger(); assertNotNull("Parser result does not contain a Swagger instance", swagger); Map<String, Model> definitions = swagger.getDefinitions(); assertNotNull("Swagger instance does not contain any definitions", definitions); assertEquals("Missing/extraneous definition;", 3, definitions.size()); Model pet = definitions.get("Pet"); Model furry = definitions.get("Furry"); Model dog = definitions.get("Dog"); assertNotNull("Pet model not found", pet); assertNotNull("Furry model not found", furry); assertNotNull("Dog model not found", dog); assertTrue("Dog model is not composed", dog instanceof ComposedModel); ComposedModel dogComposed = (ComposedModel) dog; assertNotNull("Dog does not implement any interfaces", dogComposed.getInterfaces()); assertEquals("Dog implements the wrong number of interfaces;", 2, dogComposed.getInterfaces().size()); RefModel dogInterfaceRef = dogComposed.getInterfaces().get(0); Model dogInterface = definitions.get(dogInterfaceRef.getSimpleRef()); assertEquals("Dog does not implement Pet;", pet, dogInterface); dogInterfaceRef = dogComposed.getInterfaces().get(1); dogInterface = definitions.get(dogInterfaceRef.getSimpleRef()); assertEquals("Dog does not implement Furry;", furry, dogInterface); assertTrue("Dog does not have child properties", dogComposed.getChild() instanceof ModelImpl); } @Test public void testPR246() throws Exception { String yaml = "swagger: '2.0'\n" + "info:\n" + " description: 'Tests the allOf API for parent, interface and child models.'\n" + " version: '2.0.0'\n" + " title: 'Test allOf API'\n" + "paths:\n" + " /:\n" + " get:\n" + " parameters: []\n" + " responses:\n" + " 200:\n" + " description: 'OK'\n" + " parameters: []\n" + "definitions:\n" + " Pet:\n" + " type: 'object'\n" + " required:\n" + " - 'id'\n" + " properties:\n" + " id:\n" + " type: 'integer'\n" + " format: 'int64'\n" + " Furry:\n" + " type: 'object'\n" + " required:\n" + " - 'coatColour'\n" + " properties:\n" + " coatColour:\n" + " type: 'string'\n" + " Dog:\n" + " allOf:\n" + " - $ref: '#/definitions/Pet'\n" + " - $ref: '#/definitions/Furry'\n" + " - type: object\n" + " required:\n" + " - 'name'\n" + " properties:\n" + " name:\n" + " type: 'string'\n" + ""; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(yaml); Swagger swagger = result.getSwagger(); Model dog = swagger.getDefinitions().get("Dog"); assertNotNull(dog); assertTrue(dog instanceof ComposedModel); ComposedModel composed = (ComposedModel) dog; assertTrue(composed.getChild() instanceof ModelImpl); assertTrue(composed.getInterfaces().size() == 2); } @Test public void testIssue247() { String yaml = "swagger: '2.0'\n" + "info:\n" + " description: 'bleh'\n" + " version: '2.0.0'\n" + " title: 'Test'\n" + "paths:\n" + " /:\n" + " get:\n" + " parameters: []\n" + " responses:\n" + " 200:\n" + " description: 'OK'\n" + " parameters: []\n" + "definitions:\n" + " Pet:\n" + " allOf:\n" + " - type: 'object'\n" + " required:\n" + " - 'id'\n" + " properties:\n" + " id:\n" + " type: 'integer'\n" + " format: 'int64'"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(yaml); Swagger swagger = result.getSwagger(); assertNotNull(swagger.getDefinitions().get("Pet")); } @Test public void testIssue343Parameter() { String yaml = "swagger: '2.0'\n" + "info:\n" + " description: 'bleh'\n" + " version: '2.0.0'\n" + " title: 'Test'\n" + "paths:\n" + " /foo:\n" + " post:\n" + " parameters:\n" + " - in: query\n" + " name: skip\n" + " type: integer\n" + " format: int32\n" + " multipleOf: 3\n" + " - in: body\n" + " name: body\n" + " required: true\n" + " schema:\n" + " type: object\n" + " additionalProperties:\n" + " type: string\n" + " responses:\n" + " 200:\n" + " description: 'OK'\n" + "definitions:\n" + " Fun:\n" + " properties:\n" + " id:\n" + " type: integer\n" + " format: int32\n" + " multipleOf: 5\n" + " mySet:\n" + " type: array\n" + " uniqueItems: true\n" + " items:\n" + " type: string"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(yaml); Swagger swagger = result.getSwagger(); QueryParameter qp = (QueryParameter)swagger.getPath("/foo").getPost().getParameters().get(0); assertEquals(qp.getMultipleOf(), 3.0); BodyParameter bp = (BodyParameter) swagger.getPath("/foo").getPost().getParameters().get(1); ModelImpl schema = (ModelImpl)bp.getSchema(); assertTrue(schema.getAdditionalProperties() != null); IntegerProperty id = (IntegerProperty)swagger.getDefinitions().get("Fun").getProperties().get("id"); assertEquals(id.getMultipleOf(), new BigDecimal("5")); ArrayProperty ap = (ArrayProperty)swagger.getDefinitions().get("Fun").getProperties().get("mySet"); assertTrue(ap.getUniqueItems()); } @Test public void testIssue386() { String yaml = "swagger: '2.0'\n" + "info:\n" + " description: 'bleh'\n" + " version: '2.0.0'\n" + " title: 'Test'\n" + "paths:\n" + " /foo:\n" + " post:\n" + " parameters:\n" + " - in: body\n" + " name: ugly\n" + " schema:\n" + " type: object\n" + " enum:\n" + " - id: fun\n" + " properties:\n" + " id:\n" + " type: string\n" + " responses:\n" + " 200:\n" + " description: 'OK'\n" + "definitions:\n" + " Fun:\n" + " type: object\n" + " properties:\n" + " complex:\n" + " enum:\n" + " - id: 110\n" + " type: object\n" + " properties:\n" + " id:\n" + " type: string\n" + " MyEnum:\n" + " type: integer\n" + " enum:\n" + " - value: 3\n" + " description: Value 1\n" + " - value: 10\n" + " description: Value 2"; SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(yaml); Swagger swagger = result.getSwagger(); assertNotNull(swagger); } @Test public void testIssue360() { Swagger swagger = new Swagger(); ModelImpl model = new ModelImpl()._enum((String) null); swagger.addDefinition("modelWithNullEnum", model); String json = Json.pretty(swagger); SwaggerParser parser = new SwaggerParser(); SwaggerDeserializationResult result = parser.readWithInfo(json); Swagger rebuilt = result.getSwagger(); assertNotNull(rebuilt); } }