Repository: swagger-api/swagger-parser
Pull request #1712 (2022-04-21 02:10:39)

getMediaType: Report an error for any encoding property not defined in the schema.
Fixes issue #1711 


Patch:
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 503a0a19..95d3d20e 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.Matcher;
 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 class OpenAPIDeserializer {
 			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<String> 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<String, Object> extensions = getExtensions(contentNode);
 		if (extensions != null && extensions.size() > 0) {


Test patch:
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 e5e1b655..5b2bb451 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 class OpenAPIDeserializerTest {
         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 =