Skip to content

Commit a060663

Browse files
committed
added schema mapping documentation (openapi-processor/openapi-processor-base#225)
1 parent 97e39fc commit a060663

File tree

3 files changed

+188
-1
lines changed

3 files changed

+188
-1
lines changed

docs/modules/ROOT/nav.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
** xref:mapping/structure.adoc[Type Mapping Structure]
1818
** xref:mapping/basic.adoc[Default Type Mapping]
1919
** xref:mapping/global.adoc[Global Type Mapping]
20+
** xref:mapping/schema.adoc[Global Schema Mapping]
2021
** xref:mapping/parameter.adoc[Global Parameter Mapping]
2122
** xref:mapping/response.adoc[Global Response Mapping]
2223
** xref:mapping/result.adoc[Global Result Mapping]
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
= (global) Schema mappings
2+
3+
[.badge .badge-since]+since 2025.1+
4+
5+
Schema mappings add a new (global) mapping level. They apply only to (object, i.e. dto) schema properties.
6+
7+
That means the mappings is only used when the source type is used as a property type in a generated dto class.
8+
9+
[NOTE]
10+
====
11+
This is (currently) only supported on the global level and only for xref::mapping/annotation.adoc[].
12+
====
13+
14+
Schema mappings try to solve the case where a type should be annotated, but *only* if is used in a generated dto object. Especially it should *not* annotate parameters.
15+
16+
The example will make this more clear.
17+
18+
== Example
19+
20+
In the example OpenAPI below is a year value (<1>) that is used on the response schema and as query parameter.
21+
22+
[source,yaml]
23+
----
24+
openapi: 3.1.0
25+
info:
26+
title: schema mapping
27+
version: 1.0.0
28+
29+
paths:
30+
31+
/foo:
32+
get:
33+
parameters:
34+
- name: year
35+
description: year parameter
36+
in: query
37+
required: true
38+
schema:
39+
type: integer # <1>
40+
format: year
41+
responses:
42+
'200':
43+
description: the foo result
44+
content:
45+
application/json:
46+
schema:
47+
$ref: '#/components/schemas/Foo'
48+
49+
components:
50+
schemas:
51+
52+
Foo:
53+
type: object
54+
properties:
55+
year:
56+
type: integer # <1>
57+
format: year
58+
----
59+
60+
Using a typical mapping the processor will use `java.time.Year` instead of a simple `Integer` type in the generated code.
61+
62+
[source,yaml]
63+
----
64+
openapi-processor-mapping: v11
65+
66+
options:
67+
package-name: generated
68+
format-code: false
69+
70+
map:
71+
types:
72+
- type: integer:year => java.time.Year
73+
----
74+
75+
Spring (with Jackson) may not serialize the type in the expected format by default. In case of `java.time.Year` it will be `String` and not a number.
76+
77+
To change serialization Jackson provides the `JsonFormat` annotation:
78+
79+
@JsonFormat(JsonFormat.Shape.NUMBER_INT)
80+
81+
would change serialization of `java.time.Year` to a number.
82+
83+
84+
Adding the annotation mapping for this at the global type level
85+
86+
[source,yaml]
87+
----
88+
openapi-processor-mapping: v11
89+
90+
options:
91+
package-name: generated
92+
format-code: false
93+
94+
map:
95+
types:
96+
- type: integer:year => java.time.Year
97+
- type: integer:year @ com.fasterxml.jackson.annotation.JsonFormat(shape = com.fasterxml.jackson.annotation.JsonFormat.Shape.NUMBER_INT)
98+
----
99+
100+
would add the annotation, but not only in the dto, as wanted
101+
102+
[source,java]
103+
----
104+
package generated.model;
105+
106+
import com.fasterxml.jackson.annotation.JsonFormat;
107+
import com.fasterxml.jackson.annotation.JsonProperty;
108+
import generated.support.Generated;
109+
import java.time.Year;
110+
111+
@Generated(value = "openapi-processor-core", version = "latest")
112+
public class Foo {
113+
114+
@JsonFormat(shape = JsonFormat.Shape.NUMBER_INT)
115+
@JsonProperty("year")
116+
private Year year;
117+
118+
// ...
119+
}
120+
----
121+
122+
but also at the method parameter of the generated interface:
123+
124+
[source,java]
125+
----
126+
package generated.api;
127+
128+
import com.fasterxml.jackson.annotation.JsonFormat;
129+
import generated.model.Foo;
130+
import generated.support.Generated;
131+
import java.time.Year;
132+
import org.springframework.web.bind.annotation.GetMapping;
133+
import org.springframework.web.bind.annotation.RequestParam;
134+
135+
@Generated(value = "openapi-processor-core", version = "test")
136+
public interface Api {
137+
138+
@GetMapping(path = "/foo", produces = {"application/json"})
139+
Foo getFoo(@RequestParam(name = "year", required = false) @JsonFormat(shape = JsonFormat.Shape.NUMBER_INT) Year year);
140+
141+
}
142+
----
143+
144+
That is not wanted. To avoid it, the annotation mapping should be added to the new `schemas` mapping level:
145+
146+
[source,yaml]
147+
----
148+
openapi-processor-mapping: v11
149+
150+
options:
151+
package-name: generated
152+
format-code: false
153+
154+
map:
155+
types:
156+
- type: integer:year => java.time.Year
157+
158+
schemas:
159+
- type: integer:year @ com.fasterxml.jackson.annotation.JsonFormat(shape = com.fasterxml.jackson.annotation.JsonFormat.Shape.NUMBER_INT)
160+
----
161+
162+
This tell the processor to add it only to the generated dto class and not to the interface.
163+
164+
[source,java]
165+
----
166+
package generated.api;
167+
168+
import generated.model.Foo;
169+
import generated.support.Generated;
170+
import java.time.Year;
171+
import org.springframework.web.bind.annotation.GetMapping;
172+
import org.springframework.web.bind.annotation.RequestParam;
173+
174+
@Generated(value = "openapi-processor-core", version = "test")
175+
public interface Api {
176+
177+
@GetMapping(path = "/foo", produces = {"application/json"})
178+
Foo getFoo(@RequestParam(name = "year", required = false) Year year);
179+
180+
}
181+
----

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ The mapping file needs the following key on the top-level. Best place is the fir
1515
1616
[source,yaml]
1717
----
18-
openapi-processor-mapping: v10
18+
openapi-processor-mapping: v11
1919
----
2020
====
2121

@@ -61,6 +61,11 @@ map:
6161
# add an extra annotation to the source type
6262
- type: {source type} @ {target type}
6363
64+
# list of global schema mappings
65+
schemas:
66+
# add an extra annotation to the source type, but only object properties
67+
- type: {source type} @ {target type}
68+
6469
# list of global parameter mappings
6570
parameters:
6671
- name: {parameter name} => {target type}

0 commit comments

Comments
 (0)