Skip to content

Commit 4494ae5

Browse files
committed
1 parent f2eded4 commit 4494ae5

File tree

4 files changed

+250
-8
lines changed

4 files changed

+250
-8
lines changed

docs/modules/ROOT/nav.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
** xref:mapping/single-multi.adoc[Global Single & Multi Mapping]
2828
** xref:mapping/endpoint.adoc[Endpoint Mapping]
2929
** xref:mapping/annotation.adoc[Annotation Mapping]
30+
** xref:mapping/interface.adoc[Interface Mapping]
3031
** xref:mapping/extension.adoc[Extension Mapping]
3132
** xref:mapping/null.adoc[Null Mapping]
3233
** xref:mapping/package-name.adoc[package-name Mapping]

docs/modules/ROOT/pages/mapping/index.adoc

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,29 @@
22

33
Type mapping is an important feature of the processor and helps it to create the expected code.
44

5-
Using type mapping, we can tell the processor to map types (schemas) from an openapi.yaml description to a specific existing java type instead of generating a model class from the source OpenAPI type.
5+
Using type mapping, we can tell the processor to map a type (or schema) from an openapi.yaml description to a specific existing java type instead of generating a model class from the source OpenAPI type.
66

7-
This can be a type created by us or a type from a framework. For example, to map paging parameters and result to the Spring types `Page<>` & `Pageable`.
7+
This can be a type created by ourselves or a type from a framework. For example, to map paging parameters and result to the Spring types `Page<>` & `Pageable`.
88

99
It can also be used to map the OpenAPI `array` type to a different java collection type if the default does not fulfill our needs.
1010

1111
Type mapping is very flexible. It is possible to define the mapping globally, globally for a specific response or parameter or limited to a specific endpoint or even http method for an endpoint.
1212

13-
Type mapping also supports (nested) generic parameters to the target type. Multiple levels.
13+
Type mapping also supports (nested) generic parameters of the target type. Multiple levels.
1414

15+
[NOTE]
16+
====
1517
Type mapping works best with named schemas (i.e., schemas `$ref` erenced by their name).
18+
====
19+
20+
openapi-processor offers two other kinds of type mappings that _modify_ the generated target type instead of _mapping_ to an existing type.
21+
22+
== annotation type mapping
23+
24+
annotation mapping adds a given annotation to the generated target type.
25+
26+
== interface type mapping
27+
28+
interface mapping adds the given interface to the `implements` list of the generated target type.
29+
30+
Since the processor can't provide implementations for the interface methods, the interface should be a marker interface or overlap with the generated target type.
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
= Interface mapping
2+
include::partial$links.adoc[]
3+
include::partial$vars.adoc[]
4+
5+
[.badge .badge-since]+since 2026.1+
6+
7+
It is possible to let the generated `target type` implement an interface. Currently, this is available as
8+
9+
* global _interface type mapping_:
10+
+
11+
it adds a given interface to the `implements` list of the *model class* generated for the `source type`. +
12+
+
13+
14+
* global & endpoint parameter _interface mapping_:
15+
+
16+
it adds an interface to a *parameter* of the `source type` (this includes request body parameters).
17+
18+
The global interface mapping should be added to the `map/types` or `map/parameters` section in the mapping.yaml.
19+
20+
The endpoint (http method) mapping restricts the mapping to a specific endpoint. This will go to the `map/paths/<endpoint path>/parameters` section in the mapping.yaml.
21+
22+
The interface mapping is similar to other mappings and is defined like this:
23+
24+
[source,yaml]
25+
----
26+
type: {source type} =+ {interface type}
27+
----
28+
29+
or alternatively
30+
31+
[source,yaml]
32+
----
33+
type: {source type} implement {interface type}
34+
----
35+
36+
37+
* **type** is required.
38+
39+
** **{source type}** is the type name used in the OpenAPI description and also the name of the generated target type. The target type has to be a Java type that accepts an `implements` clause.
40+
41+
** **{interface type}** is the fully qualified class name of the java interface type. It may have parameters (see the examples below).
42+
43+
Here are a few examples:
44+
45+
[source,yaml]
46+
----
47+
- type: Foo =+ java.io.Serializable
48+
- type: Foo implement java.io.Serializable
49+
- type: Foo implement some.Interface<java.lang.String>
50+
----
51+
52+
*`object` source type*
53+
54+
it is also possible to add an interface to **all** generated schema/model classes using a single interface mapping:
55+
56+
[source,yaml]
57+
----
58+
- type: object =+ {interface type}
59+
----
60+
61+
The `object` string represents **all** generated object classes (i.e., schema/model classes) and will add the given interface to all of them.
62+
63+
For example, a mapping like this:
64+
65+
[source,yaml]
66+
----
67+
map:
68+
types:
69+
- type: object =+ java.io.Serializable
70+
----
71+
72+
[source,java]
73+
----
74+
import java.io.Serializable;
75+
76+
@Generated(...)
77+
public class Foo implements Serializable {
78+
...
79+
}
80+
----
81+
82+
The link:{oap-samples}[samples project] has a small example using annotation mappings.
83+
84+
== combining interface mapping and type mapping
85+
86+
Type mapping replaces the generated class with an *existing* Java type. It is not possible to add an interface to an existing class.
87+
88+
== mapping example
89+
90+
The following OpenAPI description describes a simple endpoint which returns a Foo schema. In the mapping file we add an interface mapping for `java.io.Serializable`. This will generate a `Foo` record (or class) that implements the interface.
91+
92+
[source,yaml,subs=attributes+]
93+
----
94+
openapi: {var-openapi-version}
95+
info:
96+
title: interface mapping
97+
version: 1.0.0
98+
99+
paths:
100+
101+
/foo:
102+
get:
103+
responses:
104+
'200':
105+
description: the foo result
106+
content:
107+
application/json:
108+
schema:
109+
$ref: '#/components/schemas/Foo'
110+
111+
components:
112+
schemas:
113+
114+
Foo:
115+
type: object
116+
properties:
117+
foo:
118+
type: string
119+
----
120+
121+
and a `mapping.yaml` with annotation type mappings:
122+
123+
[source,yaml,subs=attributes+]
124+
----
125+
openapi-processor-mapping: {var-mapping-version} # <1>
126+
127+
options:
128+
package-name: io.openapiprocessor.openapi
129+
model-type: record # generate record instead of pojo
130+
131+
map:
132+
types:
133+
- type: Foo =+ java.io.Serializable # <1>
134+
----
135+
136+
<1> the interface mapping
137+
138+
Here is the generated `Foo` record:
139+
140+
[source,java]
141+
----
142+
package io.openapiprocessor.samples.model;
143+
144+
import com.fasterxml.jackson.annotation.JsonProperty;
145+
import io.openapiprocessor.samples.FooAnnotation;
146+
import io.openapiprocessor.samples.support.Generated;
147+
import jakarta.validation.Valid;
148+
import jakarta.validation.constraints.Size;
149+
import java.io.Serializable;
150+
import java.util.UUID;
151+
152+
@Generated(value = "openapi-processor-spring")
153+
public record Foo(@JsonProperty("foo") String foo)
154+
implements Serializable { // <1>
155+
}
156+
----
157+
158+
<1> it implements the given interface

docs/modules/ROOT/pages/mapping/structure.adoc

Lines changed: 73 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
include::partial$links.adoc[]
33
include::partial$vars.adoc[]
44

5-
The type mapping is part of the mapping YAML (see xref:processor/configuration.adoc[Configuration]) and configured under the `map` key. The `map` key contains multiple sections to define the different kinds of type mappings.
5+
The type mapping is part of the mapping YAML (see xref:processor/configuration.adoc[Configuration]) and configured under the `map` key. The `map` key contains multiple sections to define the different kinds of type mapping.
66

77
All sections are optional.
88

@@ -12,7 +12,7 @@ All sections are optional.
1212

1313
[IMPORTANT]
1414
====
15-
The mapping file needs the following key on the top-level. Best place is the first line of the `mapping.yaml` file.
15+
The mapping file needs the following key on the top-level. The best place is the first line of the `mapping.yaml` file.
1616
1717
[source,yaml,subs=attributes+]
1818
----
@@ -23,9 +23,9 @@ openapi-processor-mapping: {var-mapping-version}
2323
The version increases from time to time when openapi-processor requires a new or changed configuration. In case the version changes, it is mentioned in the release notes.
2424

2525

26-
=== basic mapping
26+
=== basic type mapping
2727

28-
To map a source type to a destination type, it is using an `=>` arrow as a *mapping operator* instead of individual keywords:
28+
To *map* a source type to a destination type, use the *mapping operator*: `=>`
2929

3030
[source,yaml]
3131
----
@@ -34,7 +34,63 @@ some-key: {source type} => {target type}
3434
3535
----
3636

37-
*source type* is usually a name (or type) from the OpenAPI description and *target type* is usually a java type.
37+
Usually, *source type* is a name (or type) from the OpenAPI description, and *target type* is a java type.
38+
39+
[.badge .badge-since]+since 2026.1+
40+
41+
Alternatively, if the operator is too cryptic, it is possible to use the *map* keyword instead of the operator.
42+
43+
[source,yaml]
44+
----
45+
46+
some-key: {source type} map {target type}
47+
48+
----
49+
50+
51+
=== basic annotation mapping
52+
53+
To *annotate* the generated target type, use the *annotation operator*: `@`
54+
55+
[source,yaml]
56+
----
57+
58+
some-key: {source type} @ {target type}
59+
60+
----
61+
62+
[.badge .badge-since]+since 2026.1+
63+
64+
Alternatively, if the operator is too cryptic, it is possible to use the *annotate* keyword instead of the operator.
65+
66+
[source,yaml]
67+
----
68+
69+
some-key: {source type} annotate {target type}
70+
71+
----
72+
73+
=== basic interface mapping
74+
75+
[.badge .badge-since]+since 2026.1+
76+
77+
To let the generated target type *implement* an interface, use the *interface operator*: `=+`
78+
79+
[source,yaml]
80+
----
81+
82+
some-key: {source type} =+ {target type}
83+
84+
----
85+
86+
Alternatively, if the operator is too cryptic, it is possible to use the *implement* keyword instead of the operator.
87+
88+
[source,yaml]
89+
----
90+
91+
some-key: {source type} implement {target type}
92+
93+
----
3894

3995
=== full structure
4096

@@ -68,6 +124,9 @@ map:
68124
# add an extra annotation to the source type
69125
- type: {source type} @ {target type}
70126
127+
# add an extra (marker) interface to the source type
128+
- type: {source type} =+ {target type}
129+
71130
# list of global schema mappings
72131
schemas:
73132
# add an extra annotation to the source type, but only on object properties
@@ -83,6 +142,9 @@ map:
83142
# add an extra annotation to parameters of the source type
84143
- type: {source type} @ {annotation type}
85144
145+
# add an extra (marker) interface to the source type
146+
- type: {source type} =+ {target type}
147+
86148
# list of global content mappings, mapped by content type
87149
responses:
88150
- content: {content type} => {target type}
@@ -121,6 +183,9 @@ map:
121183
# add an extra annotation to the source type
122184
- type: {source type} @ {target type}
123185
186+
# add an extra (marker) interface to the source type
187+
- type: {source type} =+ {target type}
188+
124189
# list of path-specific parameter mappings
125190
parameters:
126191
- name: {parameter name} => {target type}
@@ -131,6 +196,9 @@ map:
131196
# add an extra annotation to parameters of source type
132197
- type: {source type} @ {annotation type}
133198
199+
# add an extra (marker) interface to the source type
200+
- type: {source type} =+ {target type}
201+
134202
# list of path-specific content mappings, mapped by content type
135203
responses:
136204
- content: {content type} => {target type}

0 commit comments

Comments
 (0)