mapping OpenAPI formats
Tags: openapi, java, springboot, micronaut
Published: 2023-06-08 10:00:00

> what is *openapi-processor*? [openapi-processor][oap] is an *easy-to-use* tool to generate java based (annotated) controller *interfaces* and *pojos* (model classes) from an OpenAPI yaml description. It supports *Spring Boot*, *Micronaut* with *maven* or *gradle*.

[oap]: https://openapiprocessor.io

Assume we have this simple (but useless ;-) OpenAPI description. It uses a custom integer `format` to specify that the integer parameter and response represents a _year_.

```yaml
openapi: 3.1
info:
  title: pending API
  version: 1.0.0

paths:
  /query:
    get:
      description: echo query parameter with type mapping
      parameters:
        - name: year
          description: the year
          in: query
          required: true
          schema:
            type: integer  # <1>
            format: year
      responses:
        '200':
          description: echo response
          content:
            text/plain:
              schema:
                type: integer  # <1>
                format: year
```

<1> the integer type with custom `format`.


By default, openapi-processor-spring does not know what to do with the custom format and simply maps the OpenAPI `integer` to a Java `Integer`.

###### _the generated interface code_
```java
package io.openapiprocessor.oap.api;

import io.openapiprocessor.oap.support.Generated;
import javax.validation.constraints.NotNull;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Generated(value = "openapi-processor-spring", version = "2023.2")
public interface Api {

    /**
     * echo query parameter with type mapping
     *
     * @return echo response
     */
    @GetMapping(
            path = "/query",
            produces = {"text/plain"})
    Integer getQuery(@RequestParam(name = "year") @NotNull Integer year);

}
```

Since Java has a `java.time.Year` class it could be useful to use it instead of `Integer`.

We can *easily* help openapi-processor to generate the interface with `java.time.Year` by adding a *type mapping* to the `mapping.yaml` configuration.

###### _mapping.yaml_
```yaml
openapi-processor-mapping: v3

options:
  generated-date: false
  package-name: io.openapiprocessor.oap
  bean-validation: javax
  javadoc: true

map:
  types:
    - type: integer:year => java.time.Year # <1>
```

<1> this is the interesting part of the `mapping.yaml`. It tells the processor to map the integer custom format to the `java.time.Year` class.

The left side of the arrow is the `type` : `format` combination used in the OpenAPI and on the right side is the fully qualified java class name that is used in the generated code.

Regenerating the code will now generate the interface like this:

###### the generated interface code
```java
package io.openapiprocessor.oap.api;

import io.openapiprocessor.oap.support.Generated;
import java.time.Year;
import javax.validation.constraints.NotNull;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Generated(value = "openapi-processor-spring", version = "2023.2")
public interface Api {

    /**
     * echo query parameter with type mapping
     *
     * @return echo response
     */
    @GetMapping(
            path = "/query",
            produces = {"text/plain"})
    Year getQuery(@RequestParam(name = "year") @NotNull Year year); // <1>

}
```

<1> it is now using `java.time.Year` instead of `Integer`.

Easy :-)

If such a custom type is used in a property of an OpenAPI schema, openapi-processor will use the same type mapping definition.

We can use this simple mechanism for many other types to improve the generated code, for example:

###### type mapping examples
```yaml
  - type: string:uuid => java.util.UUID
  - type: string:date-time => java.time.Instant
  - type: string:offset-date-time => java.time.OffsetDateTime
```

I'm sure you can find more useful mappings. :-)

Thanks for reading!

*summary*

This short article described how easy it is to improve the openapi-processor generated code with a type mapping. 

See the [documentation][oap] for more.