diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java index 503a0a1986..95d3d20e41 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java @@ -72,6 +72,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; +import static java.util.Collections.emptySet; public class OpenAPIDeserializer { @@ -1354,11 +1355,27 @@ public MediaType getMediaType(ObjectNode contentNode, String location, ParseResu mediaType.setSchema(getSchema(schemaObject, String.format("%s.%s", location, "schema"), result)); } - ObjectNode encodingObject = getObject("encoding", contentNode, false, location, result); if (encodingObject != null) { - mediaType.setEncoding(getEncodingMap(encodingObject, String.format("%s.%s", location, "encoding"), - result)); + String encodingLocation = String.format("%s.%s", location, "encoding"); + mediaType.setEncoding(getEncodingMap(encodingObject, encodingLocation, result)); + + // Given all properties defined for this media type object... + Set mediaTypeProperties = + mediaType.getSchema() == null? + emptySet() : + + mediaType.getSchema().get$ref() == null? + Optional.ofNullable( mediaType.getSchema().getProperties()).map( Map::keySet).orElse( emptySet()) : + + null; + + if( mediaTypeProperties != null) { + // ... report an error if an encoding is specified for an undefined property + mediaType.getEncoding().keySet().stream() + .filter( ep -> !mediaTypeProperties.contains( ep)) + .forEach( ep -> result.extra( encodingLocation, ep, encodingObject)); + } } Map extensions = getExtensions(contentNode); if (extensions != null && extensions.size() > 0) { diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java index e5e1b655e1..5b2bb451d3 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/util/OpenAPIDeserializerTest.java @@ -1277,6 +1277,159 @@ public void testBodyContent() { assertEquals( result.getMessages().size(), 2, "Messages"); } + @Test + public void testEncodingNotApplicable() { + String json = + "{" + + " \"openapi\": \"3.0.0\"," + + " \"info\": {" + + " \"title\": \"Encodings\"," + + " \"version\": \"0.0.0\"" + + " }," + + " \"paths\": {" + + " \"/properties\": {" + + " \"post\": {" + + " \"requestBody\": {" + + " \"content\": {" + + " \"multipart/form-data\": {" + + " \"schema\": {" + + " \"type\": \"object\"," + + " \"properties\": {" + + " \"X\": {" + + " \"type\": \"integer\"" + + " }," + + " \"Y\": {" + + " \"type\": \"integer\"" + + " }" + + " }" + + " }," + + " \"encoding\": {" + + " \"X\": {" + + " \"contentType\": \"application/json\"" + + " }," + + " \"Z\": {" + + " \"contentType\": \"text/plain\"" + + " }" + + " }" + + " }" + + " }" + + " }," + + " \"responses\": {" + + " \"default\": {" + + " \"description\": \"None\"" + + " }" + + " }" + + " }" + + " }," + + " \"/propertiesNone\": {" + + " \"post\": {" + + " \"requestBody\": {" + + " \"content\": {" + + " \"multipart/form-data\": {" + + " \"schema\": {" + + " \"type\": \"object\"" + + " }," + + " \"encoding\": {" + + " \"X\": {" + + " \"contentType\": \"application/json\"" + + " }," + + " \"Z\": {" + + " \"contentType\": \"text/plain\"" + + " }" + + " }" + + " }" + + " }" + + " }," + + " \"responses\": {" + + " \"default\": {" + + " \"description\": \"None\"" + + " }" + + " }" + + " }" + + " }," + + " \"/schemaNone\": {" + + " \"post\": {" + + " \"requestBody\": {" + + " \"content\": {" + + " \"application/x-www-form-urlencoded\": {" + + " \"encoding\": {" + + " \"X\": {" + + " \"contentType\": \"application/json\"" + + " }," + + " \"Z\": {" + + " \"contentType\": \"text/plain\"" + + " }" + + " }" + + " }" + + " }" + + " }," + + " \"responses\": {" + + " \"default\": {" + + " \"description\": \"None\"" + + " }" + + " }" + + " }" + + " }," + + " \"/schemaRef\": {" + + " \"post\": {" + + " \"requestBody\": {" + + " \"content\": {" + + " \"application/x-www-form-urlencoded\": {" + + " \"schema\": {" + + " \"$ref\": \"#/components/schemas/encoded\"" + + " }," + + " \"encoding\": {" + + " \"X\": {" + + " \"contentType\": \"application/json\"" + + " }," + + " \"Z\": {" + + " \"contentType\": \"text/plain\"" + + " }" + + " }" + + " }" + + " }" + + " }," + + " \"responses\": {" + + " \"default\": {" + + " \"description\": \"None\"" + + " }" + + " }" + + " }" + + " }" + + " }," + + " \"components\": {" + + " \"schemas\": {" + + " \"encoded\": {" + + " \"type\": \"object\"," + + " \"properties\": {" + + " \"X\": {" + + " \"type\": \"integer\"" + + " }," + + " \"Y\": {" + + " \"type\": \"integer\"" + + " }" + + " }" + + " }" + + " }" + + " }" + + "}" + ; + OpenAPIV3Parser parser = new OpenAPIV3Parser(); + SwaggerParseResult result = parser.readContents(json, null, null); + + assertEquals + ( result.getMessages(), + + Arrays.asList + ( "attribute paths.'/properties'(post).requestBody.content.'multipart/form-data'.encoding.Z is unexpected", + "attribute paths.'/propertiesNone'(post).requestBody.content.'multipart/form-data'.encoding.X is unexpected", + "attribute paths.'/propertiesNone'(post).requestBody.content.'multipart/form-data'.encoding.Z is unexpected", + "attribute paths.'/schemaNone'(post).requestBody.content.'application/x-www-form-urlencoded'.encoding.X is unexpected", + "attribute paths.'/schemaNone'(post).requestBody.content.'application/x-www-form-urlencoded'.encoding.Z is unexpected"), + + "Error messages"); + } + @Test public void testStyleInvalid() { String json =