Skip to content

Commit ca977f0

Browse files
authored
Merge branch 'swagger-api:master' into master
2 parents b9eb22a + 99ba4cd commit ca977f0

File tree

50 files changed

+667
-147
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+667
-147
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ The OpenAPI Specification has undergone several revisions since initial creation
2323

2424
Swagger core Version | Release Date | OpenAPI Spec compatibility | Notes | Status
2525
------------------------- | ------------ | -------------------------- | ----- | ----
26-
2.2.38 (**current stable**)| 2025-09-29 | 3.x | [tag v2.2.38](https://github.com/swagger-api/swagger-core/tree/v2.2.38) | Supported
26+
2.2.40 (**current stable**)| 2025-10-28 | 3.x | [tag v2.2.40](https://github.com/swagger-api/swagger-core/tree/v2.2.40) | Supported
27+
2.2.39 | 2025-10-13 | 3.x | [tag v2.2.39](https://github.com/swagger-api/swagger-core/tree/v2.2.39) | Supported
28+
2.2.38 | 2025-09-29 | 3.x | [tag v2.2.38](https://github.com/swagger-api/swagger-core/tree/v2.2.38) | Supported
2729
2.2.37 | 2025-09-16 | 3.x | [tag v2.2.37](https://github.com/swagger-api/swagger-core/tree/v2.2.37) | Supported
2830
2.2.36 | 2025-08-18 | 3.x | [tag v2.2.36](https://github.com/swagger-api/swagger-core/tree/v2.2.36) | Supported
2931
2.2.35 | 2025-07-31 | 3.x | [tag v2.2.35](https://github.com/swagger-api/swagger-core/tree/v2.2.35) | Supported
@@ -131,7 +133,7 @@ You need the following installed and available in your $PATH:
131133
* Jackson 2.4.5 or greater
132134

133135

134-
### To build from source (currently 2.2.39-SNAPSHOT)
136+
### To build from source (currently 2.2.41-SNAPSHOT)
135137
```
136138
# first time building locally
137139
mvn -N

modules/swagger-annotations/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<groupId>io.swagger.core.v3</groupId>
55
<artifactId>swagger-project</artifactId>
6-
<version>2.2.39-SNAPSHOT</version>
6+
<version>2.2.41-SNAPSHOT</version>
77
<relativePath>../..</relativePath>
88
</parent>
99
<modelVersion>4.0.0</modelVersion>

modules/swagger-core/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<groupId>io.swagger.core.v3</groupId>
55
<artifactId>swagger-project</artifactId>
6-
<version>2.2.39-SNAPSHOT</version>
6+
<version>2.2.41-SNAPSHOT</version>
77
<relativePath>../..</relativePath>
88
</parent>
99
<modelVersion>4.0.0</modelVersion>

modules/swagger-core/src/main/java/io/swagger/v3/core/converter/AnnotatedType.java

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
import java.lang.reflect.Type;
99
import java.util.ArrayList;
1010
import java.util.Arrays;
11+
import java.util.Comparator;
1112
import java.util.List;
1213
import java.util.Objects;
1314
import java.util.function.Function;
15+
import java.util.stream.Collectors;
1416

1517
public class AnnotatedType {
1618
private Type type;
@@ -155,11 +157,11 @@ public AnnotatedType name(String name) {
155157
}
156158

157159
public Annotation[] getCtxAnnotations() {
158-
return ctxAnnotations;
160+
return ctxAnnotations == null ? null : Arrays.copyOf(ctxAnnotations, ctxAnnotations.length);
159161
}
160162

161163
public void setCtxAnnotations(Annotation[] ctxAnnotations) {
162-
this.ctxAnnotations = ctxAnnotations;
164+
this.ctxAnnotations = ctxAnnotations == null ? null : Arrays.copyOf(ctxAnnotations, ctxAnnotations.length);
163165
}
164166

165167
public AnnotatedType ctxAnnotations(Annotation[] ctxAnnotations) {
@@ -241,49 +243,35 @@ public AnnotatedType propertyName(String propertyName) {
241243
return this;
242244
}
243245

246+
private List<Annotation> getProcessedAnnotations(Annotation[] annotations) {
247+
if (annotations == null || annotations.length == 0) {
248+
return new ArrayList<>();
249+
}
250+
return Arrays.stream(annotations)
251+
.filter(a -> {
252+
String pkg = a.annotationType().getPackage().getName();
253+
return !pkg.startsWith("java.") && !pkg.startsWith("jdk.") && !pkg.startsWith("sun.");
254+
})
255+
.sorted(Comparator.comparing(a -> a.annotationType().getName()))
256+
.collect(Collectors.toList());
257+
}
258+
244259
@Override
245260
public boolean equals(Object o) {
246-
if (this == o) {
247-
return true;
248-
}
249-
if (!(o instanceof AnnotatedType)) {
250-
return false;
251-
}
261+
if (this == o) return true;
262+
if (!(o instanceof AnnotatedType)) return false;
252263
AnnotatedType that = (AnnotatedType) o;
253-
254-
if ((type == null && that.type != null) || (type != null && that.type == null)) {
255-
return false;
256-
}
257-
258-
if (type != null && that.type != null && !type.equals(that.type)) {
259-
return false;
260-
}
261-
return Arrays.equals(this.ctxAnnotations, that.ctxAnnotations);
264+
List<Annotation> thisAnnotatinons = getProcessedAnnotations(this.ctxAnnotations);
265+
List<Annotation> thatAnnotatinons = getProcessedAnnotations(that.ctxAnnotations);
266+
return includePropertiesWithoutJSONView == that.includePropertiesWithoutJSONView &&
267+
Objects.equals(type, that.type) &&
268+
Objects.equals(thisAnnotatinons, thatAnnotatinons) &&
269+
Objects.equals(jsonViewAnnotation, that.jsonViewAnnotation);
262270
}
263271

264-
265272
@Override
266273
public int hashCode() {
267-
if (ctxAnnotations == null || ctxAnnotations.length == 0) {
268-
return Objects.hash(type, "fixed");
269-
}
270-
List<Annotation> meaningfulAnnotations = new ArrayList<>();
271-
272-
boolean hasDifference = false;
273-
for (Annotation a: ctxAnnotations) {
274-
if(!a.annotationType().getName().startsWith("sun") && !a.annotationType().getName().startsWith("jdk")) {
275-
meaningfulAnnotations.add(a);
276-
} else {
277-
hasDifference = true;
278-
}
279-
}
280-
int result = 1;
281-
result = 31 * result + (type == null ? 0 : Objects.hash(type, "fixed"));
282-
if (hasDifference) {
283-
result = 31 * result + meaningfulAnnotations.hashCode();
284-
} else {
285-
result = 31 * result + Arrays.hashCode(ctxAnnotations);
286-
}
287-
return result;
274+
List<Annotation> processedAnnotations = getProcessedAnnotations(this.ctxAnnotations);
275+
return Objects.hash(type, jsonViewAnnotation, includePropertiesWithoutJSONView, processedAnnotations);
288276
}
289277
}

modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,7 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context
11091109
}
11101110
}
11111111

1112+
dropRootRefIfComposed(schemaWithCompositionKeys);
11121113
});
11131114

11141115
if (!composedModelPropertiesAsSibling) {
@@ -1208,6 +1209,38 @@ private Stream<Annotation> getRecordComponentAnnotations(BeanPropertyDefinition
12081209
}
12091210
}
12101211

1212+
private void dropRootRefIfComposed(Schema<?> s) {
1213+
if (s == null || s.get$ref() == null) {
1214+
return;
1215+
}
1216+
1217+
if (!isComposedSchema(s)) {
1218+
return;
1219+
}
1220+
1221+
String ref = s.get$ref();
1222+
if (refMatchesAnyComposedItem(s, ref)) {
1223+
s.set$ref(null);
1224+
}
1225+
}
1226+
1227+
private boolean isComposedSchema(Schema<?> s) {
1228+
return (s.getOneOf() != null && !s.getOneOf().isEmpty())
1229+
|| (s.getAnyOf() != null && !s.getAnyOf().isEmpty())
1230+
|| (s.getAllOf() != null && !s.getAllOf().isEmpty());
1231+
}
1232+
1233+
private boolean refMatchesAnyComposedItem(Schema<?> s, String ref) {
1234+
return refMatchesInList(s.getOneOf(), ref)
1235+
|| refMatchesInList(s.getAllOf(), ref)
1236+
|| refMatchesInList(s.getAnyOf(), ref);
1237+
}
1238+
1239+
private boolean refMatchesInList(List<Schema> schemas, String ref) {
1240+
return schemas != null && schemas.stream()
1241+
.anyMatch(schema -> ref.equals(schema.get$ref()));
1242+
}
1243+
12111244
private Boolean isRecordType(BeanPropertyDefinition propDef) {
12121245
try {
12131246
if (propDef.getPrimaryMember() != null) {

modules/swagger-core/src/main/java/io/swagger/v3/core/util/Json.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@
33
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
44
import com.fasterxml.jackson.databind.ObjectMapper;
55
import com.fasterxml.jackson.databind.ObjectWriter;
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
68

79
public class Json {
810

911
private static final class ObjectMapperHolder {
1012
private static final ObjectMapper MAPPER = ObjectMapperFactory.createJson();
1113
}
1214

15+
private static final Logger LOGGER = LoggerFactory.getLogger(Json.class);
16+
1317
public static ObjectMapper mapper() {
1418
return ObjectMapperHolder.MAPPER;
1519
}
@@ -22,16 +26,17 @@ public static String pretty(Object o) {
2226
try {
2327
return pretty().writeValueAsString(o);
2428
} catch (Exception e) {
25-
e.printStackTrace();
29+
PrettyPrintHelper.emitError(LOGGER, "Error serializing object to JSON", e);
2630
return null;
2731
}
2832
}
2933

3034
public static void prettyPrint(Object o) {
3135
try {
32-
System.out.println(pretty().writeValueAsString(o).replace("\r", ""));
36+
String prettyString = pretty().writeValueAsString(o).replace("\r", "");
37+
PrettyPrintHelper.emit(LOGGER, prettyString);
3338
} catch (Exception e) {
34-
e.printStackTrace();
39+
PrettyPrintHelper.emitError(LOGGER, "Error pretty-printing JSON", e);
3540
}
3641
}
3742
}

modules/swagger-core/src/main/java/io/swagger/v3/core/util/Json31.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ private static final class ConverterMapperHolder {
2121
private static final ObjectMapper MAPPER = ObjectMapperFactory.createJsonConverter();
2222
}
2323

24-
static Logger LOGGER = LoggerFactory.getLogger(Json31.class);
24+
private static final Logger LOGGER = LoggerFactory.getLogger(Json31.class);
2525

2626
public static ObjectMapper mapper() {
2727
return ObjectMapperHolder.MAPPER;
@@ -39,16 +39,17 @@ public static String pretty(Object o) {
3939
try {
4040
return pretty().writeValueAsString(o);
4141
} catch (Exception e) {
42-
e.printStackTrace();
42+
PrettyPrintHelper.emitError(LOGGER, "Error serializing object to JSON (3.1)", e);
4343
return null;
4444
}
4545
}
4646

4747
public static void prettyPrint(Object o) {
4848
try {
49-
System.out.println(pretty().writeValueAsString(o).replace("\r", ""));
49+
String prettyString = pretty().writeValueAsString(o).replace("\r", "");
50+
PrettyPrintHelper.emit(LOGGER, prettyString);
5051
} catch (Exception e) {
51-
e.printStackTrace();
52+
PrettyPrintHelper.emitError(LOGGER, "Error pretty-printing JSON (3.1)", e);
5253
}
5354
}
5455

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package io.swagger.v3.core.util;
2+
3+
import org.slf4j.Logger;
4+
5+
import java.io.PrintWriter;
6+
import java.io.StringWriter;
7+
import java.util.function.Consumer;
8+
9+
class PrettyPrintHelper {
10+
11+
private static final ThreadLocal<Consumer<String>> OVERRIDE = new ThreadLocal<>();
12+
13+
private PrettyPrintHelper() {
14+
// utility class
15+
}
16+
17+
static void setOverride(Consumer<String> consumer) {
18+
OVERRIDE.set(consumer);
19+
}
20+
21+
static void clearOverride() {
22+
OVERRIDE.remove();
23+
}
24+
25+
static void emit(Logger logger, String message) {
26+
Consumer<String> consumer = OVERRIDE.get();
27+
if (consumer != null) {
28+
consumer.accept(message);
29+
} else {
30+
logger.debug(message);
31+
}
32+
}
33+
34+
static void emitError(Logger logger, String message, Throwable throwable) {
35+
Consumer<String> consumer = OVERRIDE.get();
36+
if (consumer != null) {
37+
StringBuilder builder = new StringBuilder(message);
38+
if (throwable != null) {
39+
builder.append(System.lineSeparator());
40+
StringWriter writer = new StringWriter();
41+
throwable.printStackTrace(new PrintWriter(writer));
42+
builder.append(writer);
43+
}
44+
consumer.accept(builder.toString());
45+
}
46+
logger.error(message, throwable);
47+
}
48+
}

modules/swagger-core/src/main/java/io/swagger/v3/core/util/Yaml.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@
33
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
44
import com.fasterxml.jackson.databind.ObjectMapper;
55
import com.fasterxml.jackson.databind.ObjectWriter;
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
68

79
public class Yaml {
810

911
private static final class ObjectMapperHolder {
1012
private static final ObjectMapper MAPPER = ObjectMapperFactory.createYaml();
1113
}
1214

15+
private static final Logger LOGGER = LoggerFactory.getLogger(Yaml.class);
16+
1317
public static ObjectMapper mapper() {
1418
return ObjectMapperHolder.MAPPER;
1519
}
@@ -22,16 +26,17 @@ public static String pretty(Object o) {
2226
try {
2327
return pretty().writeValueAsString(o);
2428
} catch (Exception e) {
25-
e.printStackTrace();
29+
PrettyPrintHelper.emitError(LOGGER, "Error serializing object to YAML", e);
2630
return null;
2731
}
2832
}
2933

3034
public static void prettyPrint(Object o) {
3135
try {
32-
System.out.println(pretty().writeValueAsString(o));
36+
String prettyString = pretty().writeValueAsString(o);
37+
PrettyPrintHelper.emit(LOGGER, prettyString);
3338
} catch (Exception e) {
34-
e.printStackTrace();
39+
PrettyPrintHelper.emitError(LOGGER, "Error pretty-printing YAML", e);
3540
}
3641
}
3742
}

modules/swagger-core/src/main/java/io/swagger/v3/core/util/Yaml31.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ private static final class ObjectMapperHolder {
1717
}
1818

1919

20-
static Logger LOGGER = LoggerFactory.getLogger(Yaml31.class);
20+
private static final Logger LOGGER = LoggerFactory.getLogger(Yaml31.class);
2121

2222
public static ObjectMapper mapper() {
2323
return ObjectMapperHolder.MAPPER;
@@ -31,16 +31,17 @@ public static String pretty(Object o) {
3131
try {
3232
return pretty().writeValueAsString(o);
3333
} catch (Exception e) {
34-
e.printStackTrace();
34+
PrettyPrintHelper.emitError(LOGGER, "Error serializing object to YAML (3.1)", e);
3535
return null;
3636
}
3737
}
3838

3939
public static void prettyPrint(Object o) {
4040
try {
41-
System.out.println(pretty().writeValueAsString(o));
41+
String prettyString = pretty().writeValueAsString(o);
42+
PrettyPrintHelper.emit(LOGGER, prettyString);
4243
} catch (Exception e) {
43-
e.printStackTrace();
44+
PrettyPrintHelper.emitError(LOGGER, "Error pretty-printing YAML (3.1)", e);
4445
}
4546
}
4647

@@ -60,4 +61,5 @@ public static Map<String, Object> jsonSchemaAsMap(Schema schema) {
6061
LOGGER.error("Exception converting jsonSchema to Map", e);
6162
return null;
6263
}
63-
}}
64+
}
65+
}

0 commit comments

Comments
 (0)