openapi-processor-spring type mapping
Tags: openapi, java, springboot
Published: 2020-08-14 08:45:24

# 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][oap-docs] for more. There is also a [playground][oap-play] to preview the processors.

# openapi-processor-spring

[openapi-processor-spring][oap-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:

```yaml
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:

```yaml
{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][oap-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`:

```yaml
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][blog].

*Originally published at [https://hauner.github.io][blog] on August 14, 2020.*

[blog]: https://hauner.github.io/blog/2020/openapi-processor-mapping
[oap-maven]: https://docs.openapiprocessor.io/maven
[oap-spring]: https://docs.openapiprocessor.io/spring
[oap-mapping]: https://docs.openapiprocessor.io/spring/mapping
[oap-docs]: https://docs.openapiprocessor.io
[oap-play]: https://playground.openapiprocessor.io
[oap-samples]: https://docs.openapiprocessor.io/samples