Skip to main content

OpenApi Parser

io.resttestgen.core.openapi;

The OpenApiParser class deals with the parsing of the OpenAPI specification. The methods of the class are constructed so that the parser is resilient and tolerant of unexpected behaviour. For example, properties not belonging to the grammar are ignored, while inconsistencies with the specification are corrected when possible.

Within the class is a map (Map<String, Object> openAPIMap) that represents the OpenAPI specification in JSON format after it has been read and deserialised. The main constructor of the class accepts a parameter of type ApiUnderTest representing a structure used to manage and test an API. The path to the OpenAPI specification in JSON format is taken and the file is read and converted into a Gson object.

One of the main methods of the class is the parse() method, the purpose of which is to parse and normalise the OpenAPI specification. If the map contains no reference to servers or paths, then two separate exceptions are thrown. Otherwise, the method continues its execution and the specification is parsed. The methods are called in this order:

  • addSchemasNames(): The purpose of this method is to enrich each schema defined in the OpenAPI speicifcation by adding an extra piece of information, namely the name of the schema itself. This name is inserted as a custom property under the key "x-schemaName".
  • solveOpenAPIrefs(): method deals with resolving and managing references ($ref) within an OpenAPI specification, ensuring that all internal references are replaced with their corresponding actual values.
  • normalizeCommonParameters(): normalises the position of common parameters in the paths of a specific OpenAPI, moving the parameters defined at path level within each operation (GET, POST, etc.), avoiding duplicates. For each path, it checks whether a "parameters" array exists, i.e. an array of parameters common to all operations in the path. If the parameters exist, it removes them from pathItem to insert them later in the individual operations. A map is constructed to uniquely identify the parameters. The location (query, header, path, cookie) is also specified in this map. If a parameter has already been redefined within the operation, it is not overwritten.
  • inferParameterTypes(): this method infers missing types in the parameters, request and response body within the OpenAPI specification. The parameter list is retrieved, if present, and the recursiveTypeInference() method is called to infer the type if it is missing. The method is recursive, so it also works with nested types or combined patterns.
  • unfoldRequiredAttributes(): this method deals with normalising the attribute of type "required" which, if present in several places in the specification, may generate inconsistency. The method scans the OpenAPI structure looking for the "required" in various elements such as: the endpoint parameters, the request body and in the response body. When a ‘required’ is found, it propagates it to the child elements using the recursive function recursiveUnfoldRequired(). This makes the OpenAPI scheme more robust and compliant with the standard.

Once these methods have been executed, an OpenApi object is created, which is then filled with the various information extracted from the specification. First, the list of servers is extracted and it is checked whether the URL is correct or malformed. If no server is valid, an exception is thrown. After that, an iteration is performed on all paths and an Operation object is created with all information, which is then added to the OpenApi type object. All general information such as title, summary, description, etc. is also added to this object.