@team-supercharge/oasg 18.3.4 → 19.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -128,42 +128,42 @@ include:
128
128
 
129
129
  The table below gives an overview of the changes (breaking, non-breaking, bug fixes) introduced in various major versions. For the resolution of breaking changes please consult the [Migration Guide](#migration-guide).
130
130
 
131
- | Component | | | | | | | | | | | | | | | | | | |
132
- |----------------------------------|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
133
- | **Internal** | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
134
- | _Core_ |✨ |💥 |✨ |🐛 |💥 |✨ |🐛 |✨ |➖ |✨ |🐛 |🐛 |➖ |💥 |💥 |✨ |💥 |🆕 |
135
- | _Linter_ |➖ |➖ |🐛 |➖ |➖ |➖ |➖ |💥 |➖ |➖ |➖ |➖ |🐛 |➖ |✨ |💥 |🆕 |
136
- | **Client Targets** | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
137
- | `android` |✨ |➖ |➖ |➖ |🐛 |💥 |➖ |➖ |💥 |➖ |➖ |➖ |➖ |➖ |➖ |➖ |🆕 |
138
- | `angular` |➖ |➖ |✨ |➖ |🐛 |💥 |➖ |➖ |➖ |🐛 |➖ |➖ |➖ |💥 |➖ |➖ |➖ |🆕 |
139
- | `dotnet` |✨ |➖ |➖ |➖ |🆕 |
140
- | `dotnet-system-text-json` |🆕➖|
141
- | `dotnet-webapi` |✨ |➖ |🆕➖|
142
- | `dotnet-webapi-system-text-json` |🆕➖|
143
- | `feign` |🐛 |🐛 |✨ |➖ |➖ |➖ |➖ |➖ |✨ |💥 |💥 |➖ |➖ |🐛 |🐛 |🆕 |
144
- | `feign-kotlin` |🐛 |🐛 |✨ |➖ |➖ |➖ |➖ |➖ |🆕 |
145
- | `plain-java` |🐛 |🐛 |🆕 |
146
- | `flutter` |➖ |➖ |➖ |➖ |➖ |🆕 |
147
- | `ios` |➖ |➖ |➖ |➖ |➖ |💥 |🐛 |➖ |➖ |➖ |✨ |➖ |💥 |➖ |➖ |✨ |🆕 |
148
- | `apple-swift` |➖ |➖ |🆕 |
149
- | `kmp` |✨ |✨ |➖ |➖ |🆕 |
150
- | `python` |🐛 |➖ |🆕 |
151
- | `python-legacy` |🐛 |➖ |💥 |➖ |🐛 |💥 |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |🆕 |
152
- | `react` |💥 |➖ |🐛 |🐛 |➖ |💥 |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |🆕 |
153
- | `typescript-axios` |✨ |➖ |🆕 |
154
- | `typescript-fetch` |✨ |➖ |🆕 |
155
- | **Server Targets** | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
156
- | `nestjs` |✨ |🐛 |💥 |💥 |➖ |💥 |✨ |➖ |➖ |🐛 |➖ |➖ |✨ |🆕 |
157
- | `python-fastapi` |➖ |➖ |➖ |➖ |🆕 |
158
- | `python-fastapi-raw-request` |➖ |➖ |➖ |➖ |🆕 |
159
- | `spring` |🐛 |🐛 |✨ |➖ |➖ |➖ |➖ |➖ |✨ |💥 |💥 |➖ |➖ |➖ |✨ |➖ |🆕 |
160
- | `spring-kotlin` |🐛 |✨ |✨ |➖ |➖ |➖ |➖ |➖ |✨ |💥 |💥 |➖ |➖ |🐛 |✨ |➖ |🆕 |
161
- | **Misc Targets** | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
162
- | `contract-testing` |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |🆕 |
163
- | `openapi` |➖ |➖ |➖ |➖ |➖ |➖ |💥 |➖ |➖ |✨ |➖ |🆕 |
164
- | `stubby` |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |💥 |➖ |➖ |➖ |➖ |🆕 |
165
- | `postman` |➖ |➖ |➖ |🆕 |
166
- | `msw` |🆕 |
131
+ | Component | | | | | | | | | | | | | | | | | | | |
132
+ |----------------------------------|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
133
+ | **Internal** | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
134
+ | _Core_ |➖ |✨ |💥 |✨ |🐛 |💥 |✨ |🐛 |✨ |➖ |✨ |🐛 |🐛 |➖ |💥 |💥 |✨ |💥 |🆕 |
135
+ | _Linter_ |➖ |➖ |➖ |🐛 |➖ |➖ |➖ |➖ |💥 |➖ |➖ |➖ |➖ |🐛 |➖ |✨ |💥 |🆕 |
136
+ | **Client Targets** | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
137
+ | `android` |➖ |✨ |➖ |➖ |➖ |🐛 |💥 |➖ |➖ |💥 |➖ |➖ |➖ |➖ |➖ |➖ |➖ |🆕 |
138
+ | `angular` |➖ |➖ |➖ |✨ |➖ |🐛 |💥 |➖ |➖ |➖ |🐛 |➖ |➖ |➖ |💥 |➖ |➖ |➖ |🆕 |
139
+ | `dotnet` |➖ |✨ |➖ |➖ |➖ |🆕 |
140
+ | `dotnet-system-text-json` |➖ |🆕➖|
141
+ | `dotnet-webapi` |➖ |✨ |➖ |🆕➖|
142
+ | `dotnet-webapi-system-text-json` |➖ |🆕➖|
143
+ | `feign` |💥 |🐛 |🐛 |✨ |➖ |➖ |➖ |➖ |➖ |✨ |💥 |💥 |➖ |➖ |🐛 |🐛 |🆕 |
144
+ | `feign-kotlin` |💥 |🐛 |🐛 |✨ |➖ |➖ |➖ |➖ |➖ |🆕 |
145
+ | `plain-java` |➖ |🐛 |🐛 |🆕 |
146
+ | `flutter` |➖ |➖ |➖ |➖ |➖ |➖ |🆕 |
147
+ | `ios` |➖ |➖ |➖ |➖ |➖ |➖ |💥 |🐛 |➖ |➖ |➖ |✨ |➖ |💥 |➖ |➖ |✨ |🆕 |
148
+ | `apple-swift` |➖ |➖ |➖ |🆕 |
149
+ | `kmp` |➖ |✨ |✨ |➖ |➖ |🆕 |
150
+ | `python` |➖ |🐛 |➖ |🆕 |
151
+ | `python-legacy` |➖ |🐛 |➖ |💥 |➖ |🐛 |💥 |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |🆕 |
152
+ | `react` |➖ |💥 |➖ |🐛 |🐛 |➖ |💥 |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |🆕 |
153
+ | `typescript-axios` |➖ |✨ |➖ |🆕 |
154
+ | `typescript-fetch` |➖ |✨ |➖ |🆕 |
155
+ | **Server Targets** | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
156
+ | `nestjs` |➖ |✨ |🐛 |💥 |💥 |➖ |💥 |✨ |➖ |➖ |🐛 |➖ |➖ |✨ |🆕 |
157
+ | `python-fastapi` |➖ |➖ |➖ |➖ |➖ |🆕 |
158
+ | `python-fastapi-raw-request` |➖ |➖ |➖ |➖ |➖ |🆕 |
159
+ | `spring` |💥 |🐛 |🐛 |✨ |➖ |➖ |➖ |➖ |➖ |✨ |💥 |💥 |➖ |➖ |➖ |✨ |➖ |🆕 |
160
+ | `spring-kotlin` |💥 |🐛 |✨ |✨ |➖ |➖ |➖ |➖ |➖ |✨ |💥 |💥 |➖ |➖ |🐛 |✨ |➖ |🆕 |
161
+ | **Misc Targets** | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
162
+ | `contract-testing` |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |🆕 |
163
+ | `openapi` |➖ |➖ |➖ |➖ |➖ |➖ |➖ |💥 |➖ |➖ |✨ |➖ |🆕 |
164
+ | `stubby` |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |➖ |💥 |➖ |➖ |➖ |➖ |🆕 |
165
+ | `postman` |➖ |➖ |➖ |➖ |🆕 |
166
+ | `msw` |➖ |🆕 |
167
167
 
168
168
  **Legend:**
169
169
 
@@ -1195,6 +1195,26 @@ Validations from OpenAPI spec:
1195
1195
  | apiKey | Api key of nuget source (If not specified, provide the CI_JOB_TOKEN) | N | - |
1196
1196
  | generatorCustomArgs | Custom arguments of the generator (--global-property, --additional-properties) | N | - |
1197
1197
 
1198
+ > **Nullable object/enum references.** A property spec'd nullable as a
1199
+ > reference to a named schema — `nullable: true` alongside a `$ref` (OpenAPI
1200
+ > 3.0, typically via an `allOf` wrapper) or `oneOf: [$ref, {type: 'null'}]`
1201
+ > (OpenAPI 3.1) — now generates a nullable C# type (`Category?`), matching the
1202
+ > TypeScript targets' `Category | null`, regardless of whether the property is
1203
+ > `required`: `required` only governs presence of the key, never nullness of
1204
+ > the value. Previously only *optional, non-nullable* references got a `?`;
1205
+ > nullable references (required or not) silently generated a non-nullable
1206
+ > type, forcing consumers to suppress with `null!` and losing the compiler's
1207
+ > null-reference warnings at the point of use.
1208
+ >
1209
+ > Nullable **containers** (arrays, maps) are unaffected by this change and
1210
+ > still generate a non-nullable collection type.
1211
+ >
1212
+ > This applies to the `dotnet`, `dotnet-webapi` and
1213
+ > `dotnet-webapi-system-text-json` targets. `dotnet-system-text-json`
1214
+ > (`generichost`) already handled this correctly. To opt out entirely, disable
1215
+ > nullable reference types via `generatorCustomArgs`:
1216
+ > `--additional-properties=nullableReferenceTypes=false`.
1217
+
1198
1218
  #### `dotnet-system-text-json`
1199
1219
 
1200
1220
  An AOT-oriented C# **client library**. Unlike `dotnet` (which uses the
@@ -1519,6 +1539,47 @@ setupWorker(
1519
1539
 
1520
1540
  This section covers the breaking changes and their migrations across major version upgrades.
1521
1541
 
1542
+ ## From `18.x.x` to `19.0.0`
1543
+
1544
+ ### Breaking in `spring`, `spring-kotlin`, `feign` and `feign-kotlin` targets
1545
+
1546
+ SDK jars produced by these targets now target **Spring Boot 4** and **Jackson 3**, which moved to
1547
+ the new `tools.jackson` group. Consumers must upgrade accordingly, or pin the previous baseline via
1548
+ `generatorCustomArgs` in their _OASg_ `config.json`:
1549
+
1550
+ ```json
1551
+ "generatorCustomArgs": "-puseSpringBoot3=true -puseSpringBoot4=false -puseJackson3=false -popenApiNullable=true"
1552
+ ```
1553
+
1554
+ ### Breaking in `spring` and `feign` targets
1555
+
1556
+ `openApiNullable` is now disabled, as the `jackson-databind-nullable` library behind it is Jackson 2
1557
+ only. `nullable: true` properties are generated as plain types instead of `JsonNullable<T>`.
1558
+
1559
+ ### Breaking in `spring-kotlin` and `feign-kotlin` targets
1560
+
1561
+ API interface methods have no default implementation anymore and fail compilation unless the consumer
1562
+ overrides them. To keep the previous behaviour, set `skipDefaultInterface=false` back via
1563
+ `generatorCustomArgs` in your _OASg_ `config.json`.
1564
+
1565
+ ## From `18.2.x` to `18.3.0`
1566
+
1567
+ These changes shipped in `18.3.0` with the update to _OpenAPI Generator_ `7.22.0`.
1568
+
1569
+ ### Breaking in `spring-kotlin` and `feign-kotlin` targets
1570
+
1571
+ 1. `oneOf` schemas with a `discriminator` are now generated as a Kotlin `sealed interface` declaring
1572
+ only the discriminator property, so subtype properties have to be reached by narrowing with `is`.
1573
+ 2. Projects overriding `model.mustache` via `templateDir` must re-fork it — it changed significantly
1574
+ upstream. See [Template Customization](#template-customization).
1575
+
1576
+ ### Breaking in `feign` and `feign-kotlin` targets
1577
+
1578
+ The generated client configuration classes (`ClientConfiguration`, `ApiKeyRequestInterceptor`, and
1579
+ `ClientPropertiesConfiguration` for OAuth specs) moved from the shared
1580
+ `org.openapitools.configuration` package to `<basePackage>.config`, so clients no longer overshadow
1581
+ each other in projects consuming several of them. Update your imports accordingly.
1582
+
1522
1583
  ## From `17.x.x` to `18.0.0`
1523
1584
 
1524
1585
  ### Breaking in `react` target
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@team-supercharge/oasg",
3
- "version": "18.3.4",
3
+ "version": "19.0.1",
4
4
  "description": "Node-based tool to lint OpenAPI documents and generate clients, servers and documentation from them",
5
5
  "author": "Supercharge",
6
6
  "license": "MIT",
@@ -0,0 +1,165 @@
1
+ {{>partial_header}}
2
+ using System;
3
+ using System.Linq;
4
+ using System.Text;
5
+ using System.Collections.Generic;
6
+ using System.ComponentModel;
7
+ using System.ComponentModel.DataAnnotations;
8
+ using System.Runtime.Serialization;
9
+ using Newtonsoft.Json;
10
+ using {{packageName}}.Converters;
11
+ {{#models}}
12
+ {{#model}}
13
+ {{/model}}
14
+ {{/models}}
15
+
16
+ {{#models}}
17
+ {{#model}}
18
+ namespace {{modelPackage}}
19
+ { {{#isEnum}}{{>enumClass}}{{/isEnum}}{{^isEnum}}
20
+ /// <summary>
21
+ /// {{description}}
22
+ /// </summary>
23
+ [DataContract]
24
+ public {{#modelClassModifier}}{{.}} {{/modelClassModifier}}class {{classname}} : {{#parent}}{{{.}}}, {{/parent}}IEquatable<{{classname}}>
25
+ {
26
+ {{#vars}}
27
+ {{#items.isEnum}}
28
+ {{#items}}
29
+ {{^complexType}}
30
+ {{>enumClass}}
31
+ {{/complexType}}
32
+ {{/items}}
33
+ {{/items.isEnum}}
34
+ {{^items.isEnum}}
35
+ {{#isEnum}}
36
+ {{^complexType}}
37
+ {{>enumClass}}
38
+ {{/complexType}}
39
+ {{/isEnum}}
40
+ {{/items.isEnum}}
41
+ /// <summary>
42
+ /// {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}}
43
+ /// </summary>{{#description}}
44
+ /// <value>{{.}}</value>{{/description}}{{#required}}
45
+ [Required]{{/required}}{{#pattern}}
46
+ [RegularExpression("{{{.}}}")]{{/pattern}}{{#minLength}}{{#maxLength}}
47
+ [StringLength({{maxLength}}, MinimumLength={{minLength}})]{{/maxLength}}{{/minLength}}{{#minLength}}{{^maxLength}}
48
+ [MinLength({{minLength}})]{{/maxLength}}{{/minLength}}{{^minLength}}{{#maxLength}}
49
+ [MaxLength({{.}})]{{/maxLength}}{{/minLength}}{{#minimum}}{{#maximum}}
50
+ [Range({{minimum}}, {{maximum}})]{{/maximum}}{{/minimum}}
51
+ [DataMember(Name="{{baseName}}", EmitDefaultValue={{#isNullable}}true{{/isNullable}}{{^isNullable}}false{{/isNullable}})]
52
+ {{#isEnum}}
53
+ public {{{datatypeWithEnum}}}{{#isNullable}}?{{/isNullable}} {{name}} { get; set; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}
54
+ {{/isEnum}}
55
+ {{^isEnum}}
56
+ {{! this generator never appends a question mark to dataType for a nullable object/model
57
+ ref (only for primitives in its hardcoded nullable-type list), so the isModel-guarded
58
+ branch below adds it back. isModel is never set for a primitive, so this cannot
59
+ produce a double question mark. Nullable containers are intentionally left non-null
60
+ (out of scope), matching the other .NET targets in this repo. }}
61
+ public {{{dataType}}}{{#nullableReferenceTypes}}{{#isNullable}}{{#isModel}}?{{/isModel}}{{/isNullable}}{{/nullableReferenceTypes}} {{name}} { get; {{#isReadOnly}}private {{/isReadOnly}}set; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}
62
+ {{/isEnum}}
63
+ {{^-last}}
64
+
65
+ {{/-last}}
66
+ {{/vars}}
67
+
68
+ /// <summary>
69
+ /// Returns the string presentation of the object
70
+ /// </summary>
71
+ /// <returns>String presentation of the object</returns>
72
+ public override string ToString()
73
+ {
74
+ var sb = new StringBuilder();
75
+ sb.Append("class {{classname}} {\n");
76
+ {{#vars}}
77
+ sb.Append(" {{name}}: ").Append({{name}}).Append("\n");
78
+ {{/vars}}
79
+ sb.Append("}\n");
80
+ return sb.ToString();
81
+ }
82
+
83
+ /// <summary>
84
+ /// Returns the JSON string presentation of the object
85
+ /// </summary>
86
+ /// <returns>JSON string presentation of the object</returns>
87
+ public {{#parent}}{{^isMap}}{{^isArray}}new {{/isArray}}{{/isMap}}{{/parent}}string ToJson()
88
+ {
89
+ return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
90
+ }
91
+
92
+ /// <summary>
93
+ /// Returns true if objects are equal
94
+ /// </summary>
95
+ /// <param name="obj">Object to be compared</param>
96
+ /// <returns>Boolean</returns>
97
+ public override bool Equals(object obj)
98
+ {
99
+ if (obj is null) return false;
100
+ if (ReferenceEquals(this, obj)) return true;
101
+ return obj.GetType() == GetType() && Equals(({{classname}})obj);
102
+ }
103
+
104
+ /// <summary>
105
+ /// Returns true if {{classname}} instances are equal
106
+ /// </summary>
107
+ /// <param name="other">Instance of {{classname}} to be compared</param>
108
+ /// <returns>Boolean</returns>
109
+ public bool Equals({{classname}} other)
110
+ {
111
+ if (other is null) return false;
112
+ if (ReferenceEquals(this, other)) return true;
113
+
114
+ return {{#vars}}{{^isContainer}}
115
+ (
116
+ {{name}} == other.{{name}} ||
117
+ {{^vendorExtensions.x-is-value-type}}{{name}} != null &&{{/vendorExtensions.x-is-value-type}}
118
+ {{name}}.Equals(other.{{name}})
119
+ ){{^-last}} && {{/-last}}{{/isContainer}}{{#isContainer}}
120
+ (
121
+ {{name}} == other.{{name}} ||
122
+ {{^vendorExtensions.x-is-value-type}}{{name}} != null &&
123
+ other.{{name}} != null &&
124
+ {{/vendorExtensions.x-is-value-type}}{{name}}.SequenceEqual(other.{{name}})
125
+ ){{^-last}} && {{/-last}}{{/isContainer}}{{/vars}}{{^vars}}false{{/vars}};
126
+ }
127
+
128
+ /// <summary>
129
+ /// Gets the hash code
130
+ /// </summary>
131
+ /// <returns>Hash code</returns>
132
+ public override int GetHashCode()
133
+ {
134
+ unchecked // Overflow is fine, just wrap
135
+ {
136
+ var hashCode = 41;
137
+ // Suitable nullity checks etc, of course :)
138
+ {{#vars}}
139
+ {{^vendorExtensions.x-is-value-type}}if ({{name}} != null){{/vendorExtensions.x-is-value-type}}
140
+ hashCode = hashCode * 59 + {{name}}.GetHashCode();
141
+ {{/vars}}
142
+ return hashCode;
143
+ }
144
+ }
145
+
146
+ #region Operators
147
+ #pragma warning disable 1591
148
+
149
+ public static bool operator ==({{classname}} left, {{classname}} right)
150
+ {
151
+ return Equals(left, right);
152
+ }
153
+
154
+ public static bool operator !=({{classname}} left, {{classname}} right)
155
+ {
156
+ return !Equals(left, right);
157
+ }
158
+
159
+ #pragma warning restore 1591
160
+ #endregion Operators
161
+ }
162
+ {{/isEnum}}
163
+ {{/model}}
164
+ {{/models}}
165
+ }
@@ -79,7 +79,12 @@ namespace {{modelPackage}}
79
79
  public {{{datatypeWithEnum}}}{{#isNullable}}{{^required}}?{{/required}}{{/isNullable}} {{name}} { get; set; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}
80
80
  {{/isEnum}}
81
81
  {{^isEnum}}
82
- public {{{dataType}}}{{#nullableReferenceTypes}}{{^isContainer}}{{^required}}{{^isNullable}}?{{/isNullable}}{{/required}}{{/isContainer}}{{/nullableReferenceTypes}} {{name}} { get; set; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}
82
+ {{! nullable object/model refs get no question mark from the generator's dataType, unlike
83
+ primitives whose dataType already carries one -- so the isModel-guarded branch below
84
+ adds it back for those. isModel is only set for refs to named schemas, never for a
85
+ primitive whose dataType is already nullable, so this cannot produce a double question
86
+ mark. Nullable containers are intentionally left non-nullable (out of scope). }}
87
+ public {{{dataType}}}{{#nullableReferenceTypes}}{{^isContainer}}{{^required}}{{^isNullable}}?{{/isNullable}}{{/required}}{{#isNullable}}{{#isModel}}?{{/isModel}}{{/isNullable}}{{/isContainer}}{{/nullableReferenceTypes}} {{name}} { get; set; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}
83
88
  {{/isEnum}}
84
89
  {{^-last}}
85
90
 
@@ -79,7 +79,12 @@ namespace {{modelPackage}}
79
79
  public {{{datatypeWithEnum}}}{{#isNullable}}{{^required}}?{{/required}}{{/isNullable}} {{name}} { get; set; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}
80
80
  {{/isEnum}}
81
81
  {{^isEnum}}
82
- public {{{dataType}}}{{#nullableReferenceTypes}}{{^isContainer}}{{^required}}{{^isNullable}}?{{/isNullable}}{{/required}}{{/isContainer}}{{/nullableReferenceTypes}} {{name}} { get; set; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}
82
+ {{! nullable object/model refs get no question mark from the generator's dataType, unlike
83
+ primitives whose dataType already carries one -- so the isModel-guarded branch below
84
+ adds it back for those. isModel is only set for refs to named schemas, never for a
85
+ primitive whose dataType is already nullable, so this cannot produce a double question
86
+ mark. Nullable containers are intentionally left non-nullable (out of scope). }}
87
+ public {{{dataType}}}{{#nullableReferenceTypes}}{{^isContainer}}{{^required}}{{^isNullable}}?{{/isNullable}}{{/required}}{{#isNullable}}{{#isModel}}?{{/isModel}}{{/isNullable}}{{/isContainer}}{{/nullableReferenceTypes}} {{name}} { get; set; }{{#defaultValue}} = {{{.}}};{{/defaultValue}}
83
88
  {{/isEnum}}
84
89
  {{^-last}}
85
90
 
@@ -6,6 +6,10 @@
6
6
  "documentationProvider": "none",
7
7
  "annotationLibrary": "none",
8
8
  "useFeignClientContextId": false,
9
+ "useSpringBoot3": false,
10
+ "useSpringBoot4": true,
11
+ "useJackson3": true,
12
+ "openApiNullable": false,
9
13
  "typeMappings": {
10
14
  "OffsetDateTime": "Instant"
11
15
  },
@@ -0,0 +1,168 @@
1
+ {{! forked from the stock JavaSpring spring-cloud pom-sb4 to drop the hardcoded spring-security-oauth2-client version, see the FIX comment below }}
2
+ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3
+ <modelVersion>4.0.0</modelVersion>
4
+ <groupId>{{groupId}}</groupId>
5
+ <artifactId>{{artifactId}}</artifactId>
6
+ <packaging>jar</packaging>
7
+ <name>{{artifactId}}</name>
8
+ <version>{{artifactVersion}}</version>
9
+ <properties>
10
+ <java.version>17</java.version>
11
+ <maven.compiler.release>${java.version}</maven.compiler.release>
12
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
13
+ {{#springDocDocumentationProvider}}
14
+ <springdoc.version>2.2.0</springdoc.version>
15
+ {{/springDocDocumentationProvider}}
16
+ {{^springDocDocumentationProvider}}
17
+ {{#swagger2AnnotationLibrary}}
18
+ <swagger-annotations.version>2.2.15</swagger-annotations.version>
19
+ {{/swagger2AnnotationLibrary}}
20
+ {{/springDocDocumentationProvider}}
21
+ </properties>
22
+ {{#parentOverridden}}
23
+ <parent>
24
+ <groupId>{{{parentGroupId}}}</groupId>
25
+ <artifactId>{{{parentArtifactId}}}</artifactId>
26
+ <version>{{{parentVersion}}}</version>
27
+ </parent>
28
+ {{/parentOverridden}}
29
+ {{^parentOverridden}}
30
+ <parent>
31
+ <groupId>org.springframework.boot</groupId>
32
+ <artifactId>spring-boot-starter-parent</artifactId>
33
+ <version>4.0.1</version>
34
+ <relativePath/> <!-- lookup parent from repository -->
35
+ </parent>
36
+ {{/parentOverridden}}
37
+
38
+ <build>
39
+ <sourceDirectory>src/main/java</sourceDirectory>
40
+ {{#interfaceOnly}}<plugins>
41
+ <plugin>
42
+ <groupId>org.apache.maven.plugins</groupId>
43
+ <artifactId>maven-source-plugin</artifactId>
44
+ <executions>
45
+ <execution>
46
+ <id>attach-sources</id>
47
+ <goals>
48
+ <goal>jar</goal>
49
+ </goals>
50
+ </execution>
51
+ </executions>
52
+ </plugin>
53
+ </plugins>{{/interfaceOnly}}
54
+ </build>
55
+
56
+ {{^parentOverridden}}
57
+ <dependencyManagement>
58
+ <dependencies>
59
+ <dependency>
60
+ <groupId>org.springframework.cloud</groupId>
61
+ <artifactId>spring-cloud-dependencies</artifactId>
62
+ <version>2025.1.0</version>
63
+ <type>pom</type>
64
+ <scope>import</scope>
65
+ </dependency>
66
+ </dependencies>
67
+ </dependencyManagement>
68
+
69
+ {{/parentOverridden}}
70
+ <dependencies>
71
+ {{#springDocDocumentationProvider}}
72
+ <!--SpringDoc dependencies -->
73
+ <dependency>
74
+ <groupId>org.springdoc</groupId>
75
+ <artifactId>springdoc-openapi-starter-{{#reactive}}webflux{{/reactive}}{{^reactive}}webmvc{{/reactive}}-ui</artifactId>
76
+ <version>${springdoc.version}</version>
77
+ </dependency>
78
+ {{/springDocDocumentationProvider}}
79
+ {{^springDocDocumentationProvider}}
80
+ {{#swagger2AnnotationLibrary}}
81
+ <dependency>
82
+ <groupId>io.swagger.core.v3</groupId>
83
+ <artifactId>swagger-annotations</artifactId>
84
+ <version>${swagger-annotations.version}</version>
85
+ </dependency>
86
+ {{/swagger2AnnotationLibrary}}
87
+ {{/springDocDocumentationProvider}}
88
+ {{^useJspecify}}
89
+ <!-- @Nullable annotation -->
90
+ <dependency>
91
+ <groupId>com.google.code.findbugs</groupId>
92
+ <artifactId>jsr305</artifactId>
93
+ {{^parentOverridden}}
94
+ <version>3.0.2</version>
95
+ {{/parentOverridden}}
96
+ </dependency>
97
+ {{/useJspecify}}
98
+ <dependency>
99
+ <groupId>org.springframework.cloud</groupId>
100
+ <artifactId>spring-cloud-starter-openfeign</artifactId>
101
+ </dependency>
102
+ <dependency>
103
+ <groupId>org.springframework.security</groupId>
104
+ {{! FIX: the generator's built-in pom-sb4 pins 6.1.1 here, which contradicts the Spring Security version managed by the Spring Boot 4 parent. Let it resolve from the BOM. }}
105
+ <artifactId>spring-security-oauth2-client</artifactId>
106
+ </dependency>
107
+ <dependency>
108
+ <groupId>{{jacksonPackage}}.core</groupId>
109
+ <artifactId>jackson-databind</artifactId>
110
+ </dependency>
111
+ {{#withXml}}
112
+ <!-- XML processing: Jackson -->
113
+ <dependency>
114
+ <groupId>{{jacksonPackage}}.dataformat</groupId>
115
+ <artifactId>jackson-dataformat-xml</artifactId>
116
+ </dependency>
117
+ {{/withXml}}
118
+ {{^useJackson3}}
119
+ <dependency>
120
+ <groupId>com.fasterxml.jackson.datatype</groupId>
121
+ <artifactId>jackson-datatype-jsr310</artifactId>
122
+ </dependency>
123
+ {{/useJackson3}}
124
+ {{#joda}}
125
+ <dependency>
126
+ <groupId>{{jacksonPackage}}.datatype</groupId>
127
+ <artifactId>jackson-datatype-joda</artifactId>
128
+ </dependency>
129
+ {{/joda}}
130
+ {{#openApiNullable}}
131
+ <dependency>
132
+ <groupId>org.openapitools</groupId>
133
+ <artifactId>jackson-databind-nullable</artifactId>
134
+ {{^parentOverridden}}
135
+ <version>0.2.8</version>
136
+ {{/parentOverridden}}
137
+ </dependency>
138
+ {{/openApiNullable}}
139
+ {{#hateoas}}
140
+ <dependency>
141
+ <groupId>org.springframework.boot</groupId>
142
+ <artifactId>spring-boot-starter-hateoas</artifactId>
143
+ </dependency>
144
+ {{/hateoas}}
145
+ {{#lombok}}
146
+ <dependency>
147
+ <groupId>org.projectlombok</groupId>
148
+ <artifactId>lombok</artifactId>
149
+ <optional>true</optional>
150
+ </dependency>
151
+ {{/lombok}}
152
+ {{#useBeanValidation}}
153
+ <dependency>
154
+ <groupId>org.springframework.boot</groupId>
155
+ <artifactId>spring-boot-starter-validation</artifactId>
156
+ </dependency>
157
+ {{/useBeanValidation}}
158
+ <dependency>
159
+ <groupId>org.springframework.data</groupId>
160
+ <artifactId>spring-data-commons</artifactId>
161
+ </dependency>
162
+ <dependency>
163
+ <groupId>org.springframework.boot</groupId>
164
+ <artifactId>spring-boot-starter-test</artifactId>
165
+ <scope>test</scope>
166
+ </dependency>
167
+ </dependencies>
168
+ </project>
@@ -2,11 +2,14 @@
2
2
  "library": "spring-cloud",
3
3
  "gradleBuildFile": false,
4
4
  "interfaceOnly": true,
5
+ "skipDefaultInterface": true,
5
6
  "useTags": true,
6
7
  "enumPropertyNaming": "UPPERCASE",
7
8
  "documentationProvider": "none",
8
9
  "annotationLibrary": "none",
9
- "useSpringBoot3": true,
10
+ "useSpringBoot3": false,
11
+ "useSpringBoot4": true,
12
+ "useJackson3": true,
10
13
  "typeMappings": {
11
14
  "DateTime": "Instant"
12
15
  },
@@ -1,4 +1,3 @@
1
- {{! ! FIX: incompatible kotlin version - compilation fails with "The binary version of its metadata is 1.9.0, expected version is 1.7.1." - 1.7 from this POM is overriden by spring-boot-parent, and 1.8 had breaking changes }}
2
1
  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3
2
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4
3
  <modelVersion>4.0.0</modelVersion>
@@ -8,53 +7,41 @@
8
7
  <name>{{artifactId}}</name>
9
8
  <version>{{artifactVersion}}</version>
10
9
  <properties>{{#reactive}}
11
- <kotlinx-coroutines.version>1.6.1
12
- </kotlinx-coroutines.version>{{/reactive}}{{#springDocDocumentationProvider}}{{#useSwaggerUI}}
13
- <springdoc-openapi.version>2.2.0
14
- </springdoc-openapi.version>{{/useSwaggerUI}}{{/springDocDocumentationProvider}}{{#useSwaggerUI}}{{^springDocDocumentationProvider}}
15
- <swagger-ui.version>5.3.1
10
+ <kotlinx-coroutines.version>1.10.1
11
+ </kotlinx-coroutines.version>{{/reactive}}{{#springDocDocumentationProvider}}
12
+ <springdoc-openapi.version>2.8.6
13
+ </springdoc-openapi.version>{{/springDocDocumentationProvider}}{{#useSwaggerUI}}{{^springDocDocumentationProvider}}
14
+ <swagger-ui.version>5.17.14
16
15
  </swagger-ui.version>{{/springDocDocumentationProvider}}{{/useSwaggerUI}}{{^springDocDocumentationProvider}}{{#swagger1AnnotationLibrary}}
17
16
  <swagger-annotations.version>1.6.6
18
17
  </swagger-annotations.version>{{/swagger1AnnotationLibrary}}{{#swagger2AnnotationLibrary}}
19
- <swagger-annotations.version>2.2.15
18
+ <swagger-annotations.version>2.2.28
20
19
  </swagger-annotations.version>{{/swagger2AnnotationLibrary}}{{/springDocDocumentationProvider}}
21
- <findbugs-jsr305.version>3.0.2</findbugs-jsr305.version>
22
- <jakarta-annotation.version>2.1.0</jakarta-annotation.version>
23
- <kotlin-test-junit5.version>1.7.10</kotlin-test-junit5.version>
20
+ <findbugs-jsr305.version>3.0.2</findbugs-jsr305.version>{{#useJackson3}}
21
+ <jackson3.version>3.1.0</jackson3.version>{{/useJackson3}}
22
+ <jakarta-annotation.version>3.0.0</jakarta-annotation.version>
23
+ <kotlin-test-junit5.version>2.2.0</kotlin-test-junit5.version>
24
24
 
25
- {{! FIX: incompatible kotlin version }}
26
- <kotlin.version>1.9.25</kotlin.version>
25
+ <kotlin.version>2.2.0</kotlin.version>
27
26
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
28
27
  </properties>
29
28
  <parent>
30
29
  <groupId>org.springframework.boot</groupId>
31
30
  <artifactId>spring-boot-starter-parent</artifactId>
32
- <version>3.3.13</version>
31
+ <version>4.0.1</version>
33
32
  </parent>
34
33
  <dependencyManagement>
35
34
  <dependencies>
36
35
  <dependency>
37
36
  <groupId>org.springframework.cloud</groupId>
38
- <artifactId>spring-cloud-starter-parent</artifactId>
39
- <version>2023.0.6</version>
37
+ {{! FIX: the generator's built-in pom-sb4 imports spring-cloud-starter-parent, which is NOT published as a GA artifact for the 2025.1.x train (only spring-cloud-dependencies is). Use the proper importable BOM. }}
38
+ <artifactId>spring-cloud-dependencies</artifactId>
39
+ <version>2025.1.0</version>
40
40
  <type>pom</type>
41
41
  <scope>import</scope>
42
42
  </dependency>
43
43
  </dependencies>
44
44
  </dependencyManagement>
45
- <repositories>
46
- <repository>
47
- <id>repository.spring.milestone</id>
48
- <name>Spring Milestone Repository</name>
49
- <url>https://repo.spring.io/milestone</url>
50
- </repository>
51
- </repositories>
52
- <pluginRepositories>
53
- <pluginRepository>
54
- <id>spring-milestones</id>
55
- <url>https://repo.spring.io/milestone</url>
56
- </pluginRepository>
57
- </pluginRepositories>
58
45
  <build>
59
46
  <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
60
47
  <plugins>{{^interfaceOnly}}
@@ -120,7 +107,6 @@
120
107
  <dependencies>
121
108
  <dependency>
122
109
  <groupId>org.jetbrains.kotlin</groupId>
123
- {{! FIX: incompatible kotlin version }}
124
110
  <artifactId>kotlin-stdlib</artifactId>
125
111
  <version>${kotlin.version}</version>
126
112
  </dependency>
@@ -131,7 +117,7 @@
131
117
  </dependency>{{^reactive}}
132
118
  <dependency>
133
119
  <groupId>org.springframework.boot</groupId>
134
- <artifactId>spring-boot-starter-web</artifactId>
120
+ <artifactId>spring-boot-starter-webmvc</artifactId>
135
121
  </dependency>{{/reactive}}{{#reactive}}
136
122
  <dependency>
137
123
  <groupId>org.springframework.boot</groupId>
@@ -199,12 +185,29 @@
199
185
  <artifactId>spring-boot-starter-oauth2-client</artifactId>
200
186
  </dependency>
201
187
  {{/hasAuthMethods}}
188
+ {{#useJackson3}}
202
189
  <dependency>
203
- <groupId>com.fasterxml.jackson.dataformat</groupId>
190
+ <groupId>{{jacksonPackage}}.dataformat</groupId>
204
191
  <artifactId>jackson-dataformat-yaml</artifactId>
192
+ <version>${jackson3.version}</version>
205
193
  </dependency>
206
194
  <dependency>
207
- <groupId>com.fasterxml.jackson.dataformat</groupId>
195
+ <groupId>{{jacksonPackage}}.dataformat</groupId>
196
+ <artifactId>jackson-dataformat-xml</artifactId>
197
+ <version>${jackson3.version}</version>
198
+ </dependency>
199
+ <dependency>
200
+ <groupId>{{jacksonPackage}}.module</groupId>
201
+ <artifactId>jackson-module-kotlin</artifactId>
202
+ <version>${jackson3.version}</version>
203
+ </dependency>
204
+ {{/useJackson3}}{{^useJackson3}}
205
+ <dependency>
206
+ <groupId>{{jacksonPackage}}.dataformat</groupId>
207
+ <artifactId>jackson-dataformat-yaml</artifactId>
208
+ </dependency>
209
+ <dependency>
210
+ <groupId>{{jacksonPackage}}.dataformat</groupId>
208
211
  <artifactId>jackson-dataformat-xml</artifactId>
209
212
  </dependency>
210
213
  <dependency>
@@ -212,21 +215,16 @@
212
215
  <artifactId>jackson-datatype-jsr310</artifactId>
213
216
  </dependency>
214
217
  <dependency>
215
- <groupId>com.fasterxml.jackson.module</groupId>
218
+ <groupId>{{jacksonPackage}}.module</groupId>
216
219
  <artifactId>jackson-module-kotlin</artifactId>
217
220
  </dependency>
221
+ {{/useJackson3}}
218
222
  {{#useBeanValidation}}
219
223
  <!-- Bean Validation API support -->
220
224
  <dependency>
221
225
  <groupId>jakarta.validation</groupId>
222
226
  <artifactId>jakarta.validation-api</artifactId>
223
227
  </dependency>{{/useBeanValidation}}
224
- {{#openApiNullable}}
225
- <dependency>
226
- <groupId>org.openapitools</groupId>
227
- <artifactId>jackson-databind-nullable</artifactId>
228
- <version>0.2.10</version>
229
- </dependency>{{/openApiNullable}}
230
228
  <dependency>
231
229
  <groupId>jakarta.annotation</groupId>
232
230
  <artifactId>jakarta.annotation-api</artifactId>
@@ -239,10 +237,5 @@
239
237
  <version>${kotlin-test-junit5.version}</version>
240
238
  <scope>test</scope>
241
239
  </dependency>
242
- <dependency>
243
- <groupId>org.springframework.boot</groupId>
244
- <artifactId>spring-boot-starter-test</artifactId>
245
- <scope>test</scope>
246
- </dependency>
247
240
  </dependencies>
248
241
  </project>
@@ -7,6 +7,10 @@
7
7
  "enumPropertyNaming": "MACRO_CASE",
8
8
  "documentationProvider": "none",
9
9
  "annotationLibrary": "none",
10
+ "useSpringBoot3": false,
11
+ "useSpringBoot4": true,
12
+ "useJackson3": true,
13
+ "openApiNullable": false,
10
14
  "typeMappings": {
11
15
  "OffsetDateTime": "Instant"
12
16
  },
@@ -2,11 +2,14 @@
2
2
  "library": "spring-boot",
3
3
  "gradleBuildFile": false,
4
4
  "interfaceOnly": true,
5
+ "skipDefaultInterface": true,
5
6
  "useTags": true,
6
7
  "enumPropertyNaming": "UPPERCASE",
7
8
  "annotationLibrary": "none",
8
9
  "documentationProvider": "none",
9
- "useSpringBoot3": true,
10
+ "useSpringBoot3": false,
11
+ "useSpringBoot4": true,
12
+ "useJackson3": true,
10
13
  "requestMappingMode": "api_interface",
11
14
  "typeMappings": {
12
15
  "DateTime": "Instant"