loading...
Cover image for openapi-processor-spring type mapping

openapi-processor-spring type mapping

hauner profile image Martin Hauner Originally published at hauner.github.io ・4 min read

what is openapi-processor?

openapi-processor is a small framework to process OpenAPI yaml files. Currently, openapi-processor provides java code generation for Spring Boot and conversion to json.

It does support gradle and maven to run any openapi-processor as part of the build process.

See the documentation for more. There is also a playground to preview the processors.

openapi-processor-spring

openapi-processor-spring (oap-spring) generates server side Java code for Spring Boot from an OpenAPI description. It generates interfaces for the endpoints with all the required Spring annotations, and it generates model classes (simple POJOs) with Jackson annotations for the OpenAPI schemas used in those endpoints.

By creating a controller that implements a generated interface it gets easier to implement the expected endpoints. Spring will automatically pick up all annotations on the generated interface methods. You can concentrate on the implementation.

what is type mapping?

Code generation is tricky. It is impossible to generate the perfect code just from the OpenAPI description. There are many cases where the generator needs our help to generate the code we like.

Just think of collections. OpenAPI has a single schema abstraction to describe collections: the *array*. It does not need more.

Using array (e.g. String[]) in Java is possible (and that is what oap-spring is using by default) but usually we prefer a more powerful and easier to use collection like List or Set etc.

That is why we need type mapping. Type mapping allows us to map an OpenAPI schema to a specific Java class.

The generator does use the mapping to replace any occurrence of the given OpenAPI schema in the generated code with the mapped target Java type. It doesn't matter if it is a parameter, response or a property of an object schema.

If an OpenAPI model schema (which would normally generate a POJO class) gets mapped to an existing Java class oap-spring will not generate a (duplicate) POJO class.

where to specify type mappings?

Type mapping is part of the openapi-processor yaml configuration file mapping.yaml. It should be a sibling of the OpenAPI yaml files (i.e. in the same directory).

The file looks like this:

openapi-processor-mapping: v2 # <1>

options:
  package-name: io.openapiprocessor.mapping # <2>

map:
   # java type mappings # <3>

<1> sets the configuration file format. It must be present with version 2 to use the mapping format described below.

<2> sets the Java package for the generated source files.

<3> map is the parent key of all type mappings.

how to specify a type mapping?

Type mapping uses a simple notation to specify a mapping:

{collection}:  # <1>
  {key}: {source type} => {target type} # <2>

<1> this defines the mapping collection. All mappings are grouped into a couple of fixed collections: types, parameters, responses and paths. A mapping collection can have any number of mappings.

<2> key defines what kind of mapping gets defined. For example type is the key for a global type mapping in the types collection. The value of the key maps a source type to a destination type by using an \=> arrow as the mapping operator. {source type} is the name of an OpenAPI type and {target type} is the fully qualified Java class name. Fully qualified because the processor needs the package name to generate an import statement for the target type.

Let's take a look at a few mapping examples. This is just an introduction and doesn't describe all the possibilities. See the type mapping documentation for more.

type mapping examples

global mapping

The first mapping is the global type mapping. Remembering the array example from above we can change it globally to java.util.Collection:

map:
  types: # <1>
    - type: array => java.util.Collection # <2>
    - type: Foo => io.openapiprocessor.samples.Foo # <3>

<1> types is the list of global type mappings. It is global because it is a direct child of the map key.
<2> - type is an actual mapping item, and it says: map the OpenAPI array schema type to Java's java.util.Collection.

Important:
the processor assumes that the Java target of array has a single generic parameter, and it will automatically use the array's item property type as the generic parameter.

<3> this one maps an OpenAPI schema Foo to an existing Java class in our code base.

path mapping

The second mapping is path-based type mapping and it is quite useful. It allows us to limit a mapping rule to a single endpoint. It is not used for any other endpoint.

Continue reading here.

Originally published at https://hauner.github.io on August 14, 2020.

Discussion

pic
Editor guide