Skip to content

Commit b8db740

Browse files
authored
Merge branch 'master' into branch_issue_911
2 parents d018594 + eab9a28 commit b8db740

File tree

35 files changed

+1406
-732
lines changed

35 files changed

+1406
-732
lines changed

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Swagger Parser
22

3-
[![Build Status](https://img.shields.io/jenkins/s/https/jenkins.swagger.io/view/OSS%20-%20Java/job/oss-swagger-parser-2.0.svg)](https://jenkins.swagger.io/view/OSS%20-%20Java/job/oss-swagger-parser-2.0)
3+
**NOTE:** If you're looking for `swagger-parser` 1.X and OpenApi 2.0, please refer to [v1 branch](https://github.com/swagger-api/swagger-parser/tree/v1)
4+
5+
[![Build Status](https://img.shields.io/jenkins/s/https/jenkins.swagger.io/view/OSS%20-%20Java/job/oss-swagger-parser-v2.svg)](https://jenkins.swagger.io/view/OSS%20-%20Java/job/oss-swagger-parser-v2)
46

57
## Overview
68
This is the swagger parser project, which reads OpenAPI Specifications into current Java POJOs. It also provides a simple framework to add additional converters from different formats into the Swagger objects, making the entire toolchain available.
@@ -97,7 +99,7 @@ You can include this library from Sonatype OSS for SNAPSHOTS, or Maven central f
9799
<dependency>
98100
<groupId>io.swagger.parser.v3</groupId>
99101
<artifactId>swagger-parser</artifactId>
100-
<version>2.0.5</version>
102+
<version>2.0.6-SNAPSHOT</version>
101103
</dependency>
102104

103105
```
@@ -108,7 +110,7 @@ or
108110
<dependency>
109111
<groupId>io.swagger.parser.v3</groupId>
110112
<artifactId>swagger-parser</artifactId>
111-
<version>2.0.5</version>
113+
<version>2.0.6-SNAPSHOT</version>
112114
</dependency>
113115

114116
```

modules/swagger-parser-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.parser.v3</groupId>
55
<artifactId>swagger-parser-project</artifactId>
6-
<version>2.0.5</version>
6+
<version>2.0.6-SNAPSHOT</version>
77
<relativePath>../..</relativePath>
88
</parent>
99
<modelVersion>4.0.0</modelVersion>

modules/swagger-parser-v2-converter/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.parser.v3</groupId>
55
<artifactId>swagger-parser-project</artifactId>
6-
<version>2.0.5</version>
6+
<version>2.0.6-SNAPSHOT</version>
77
<relativePath>../..</relativePath>
88
</parent>
99
<modelVersion>4.0.0</modelVersion>

modules/swagger-parser-v3/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.parser.v3</groupId>
55
<artifactId>swagger-parser-project</artifactId>
6-
<version>2.0.5</version>
6+
<version>2.0.6-SNAPSHOT</version>
77
<relativePath>../..</relativePath>
88
</parent>
99
<modelVersion>4.0.0</modelVersion>

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/models/RefType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
public enum RefType {
77
COMPONENTS("#/components/"),
8+
SCHEMAS("#/components/schemas/"),
89
PATH("#/paths/");
910

1011
private final String internalPrefix;

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.swagger.v3.oas.models.media.ArraySchema;
1111
import io.swagger.v3.oas.models.media.ComposedSchema;
1212
import io.swagger.v3.oas.models.media.MediaType;
13+
import io.swagger.v3.oas.models.media.ObjectSchema;
1314
import io.swagger.v3.oas.models.media.Schema;
1415
import io.swagger.v3.oas.models.parameters.Parameter;
1516
import io.swagger.v3.oas.models.parameters.RequestBody;
@@ -18,6 +19,7 @@
1819
import io.swagger.v3.oas.models.security.SecurityScheme;
1920
import io.swagger.v3.parser.ResolverCache;
2021
import io.swagger.v3.parser.models.RefFormat;
22+
import io.swagger.v3.parser.models.RefType;
2123
import org.apache.commons.lang3.StringUtils;
2224
import org.slf4j.LoggerFactory;
2325

@@ -199,6 +201,11 @@ private void processProperties(Map<String,Schema> subProps, String file) {
199201
&& StringUtils.isNotBlank(((ArraySchema) mapProp.getAdditionalProperties()).getItems().get$ref())) {
200202
processRefSchema(((ArraySchema) mapProp.getAdditionalProperties()).getItems(), file);
201203
}
204+
}else if (prop.getValue() instanceof ObjectSchema){
205+
ObjectSchema objProp = (ObjectSchema) prop.getValue();
206+
if(objProp.getProperties() != null ){
207+
processProperties(objProp.getProperties(),file);
208+
}
202209
}
203210
}
204211
}
@@ -674,16 +681,17 @@ private void processRefSchema(Schema subRef, String externalFile) {
674681
RefFormat format = computeRefFormat(subRef.get$ref());
675682

676683
if (!isAnExternalRefFormat(format)) {
677-
processRefToExternalSchema(externalFile + subRef.get$ref(), RefFormat.RELATIVE);
684+
subRef.set$ref(RefType.SCHEMAS.getInternalPrefix()+ processRefToExternalSchema(externalFile + subRef.get$ref(), RefFormat.RELATIVE));
678685
return;
679686
}
680687
String $ref = subRef.get$ref();
681688

682689
if (format.equals(RefFormat.RELATIVE)) {
683690
$ref = constructRef(subRef, externalFile);
684691
subRef.set$ref($ref);
692+
}else {
693+
processRefToExternalSchema($ref, format);
685694
}
686-
processRefToExternalSchema($ref, computeRefFormat(subRef.get$ref()));
687695
}
688696

689697

@@ -723,4 +731,4 @@ else if("".equals(uri.getPath()) && !fragment.startsWith("/")) {
723731
}
724732

725733

726-
}
734+
}

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/SchemaProcessor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import io.swagger.v3.oas.models.media.Schema;
1010
import io.swagger.v3.parser.ResolverCache;
1111
import io.swagger.v3.parser.models.RefFormat;
12+
import io.swagger.v3.parser.models.RefType;
1213
import io.swagger.v3.parser.util.RefUtils;
1314

1415
import java.util.HashMap;
@@ -201,7 +202,7 @@ private void processReferenceSchema(Schema schema) {
201202
final String newRef = externalRefProcessor.processRefToExternalSchema($ref, refFormat);
202203

203204
if (newRef != null) {
204-
schema.set$ref(newRef);
205+
schema.set$ref(RefType.SCHEMAS.getInternalPrefix() + newRef);
205206
}
206207
}
207208
}

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ public class OpenAPIDeserializer {
9090
private static final String PATH_PARAMETER = "path";
9191
private static final String HEADER_PARAMETER = "header";
9292

93+
private final Set<String> operationIDs = new HashSet<>();
9394

9495
public SwaggerParseResult deserialize(JsonNode rootNode) {
9596
return deserialize(rootNode, null);
@@ -292,11 +293,18 @@ public List<Tag> getTagList(ArrayNode obj, String location, ParseResult result)
292293
return null;
293294
}
294295
List<Tag> tags = new ArrayList<>();
296+
Set<String> tagsTracker = new HashSet<>();
295297
for (JsonNode item : obj) {
296298
if (item.getNodeType().equals(JsonNodeType.OBJECT)) {
297299
Tag tag = getTag((ObjectNode) item, location, result);
298300
if (tag != null) {
299301
tags.add(tag);
302+
303+
if(tagsTracker.contains((String)tag.getName())) {
304+
result.uniqueTags(location,tag.getName());
305+
}
306+
307+
tagsTracker.add(tag.getName());
300308
}
301309
}
302310
}
@@ -516,6 +524,9 @@ public Paths getPaths(ObjectNode obj, String location, ParseResult result) {
516524
if (!pathValue.getNodeType().equals(JsonNodeType.OBJECT)) {
517525
result.invalidType(location, pathName, "object", pathValue);
518526
} else {
527+
if(!pathName.startsWith("/")){
528+
result.warning(location," Resource "+pathName+ " should start with /");
529+
}
519530
ObjectNode path = (ObjectNode) pathValue;
520531
PathItem pathObj = getPathItem(path,String.format("%s.'%s'", location,pathName), result);
521532
String[] eachPart = pathName.split("/");
@@ -730,7 +741,7 @@ public ExternalDocumentation getExternalDocs(ObjectNode node, String location, P
730741
}
731742

732743

733-
public String getString(String key, ObjectNode node, boolean required, String location, ParseResult result) {
744+
public String getString(String key, ObjectNode node, boolean required, String location, ParseResult result, Set<String> uniqueValues) {
734745
String value = null;
735746
JsonNode v = node.get(key);
736747
if (node == null || v == null) {
@@ -742,10 +753,18 @@ public String getString(String key, ObjectNode node, boolean required, String lo
742753
result.invalidType(location, key, "string", node);
743754
} else {
744755
value = v.asText();
756+
if (uniqueValues != null && !uniqueValues.add(value)) {
757+
result.unique(location, "operationId");
758+
result.invalid();
759+
}
745760
}
746761
return value;
747762
}
748763

764+
public String getString(String key, ObjectNode node, boolean required, String location, ParseResult result) {
765+
return getString(key, node, required, location, result, null);
766+
}
767+
749768
public Set<String> getKeys(ObjectNode node) {
750769
Set<String> keys = new LinkedHashSet<>();
751770
if (node == null) {
@@ -845,6 +864,12 @@ public License getLicense(ObjectNode node, String location, ParseResult result)
845864

846865
value = getString("url", node, false, location, result);
847866
if(StringUtils.isNotBlank(value)) {
867+
try {
868+
new URL(value);
869+
}
870+
catch (Exception e) {
871+
result.warning(location,value);
872+
}
848873
license.setUrl(value);
849874
}
850875

@@ -876,6 +901,12 @@ public Contact getContact(ObjectNode node, String location, ParseResult result)
876901

877902
value = getString("url", node, false, location, result);
878903
if(StringUtils.isNotBlank(value)) {
904+
try {
905+
new URL(value);
906+
}
907+
catch (Exception e) {
908+
result.warning(location,value);
909+
}
879910
contact.setUrl(value);
880911
}
881912

@@ -1093,6 +1124,11 @@ public Link getLink(ObjectNode linkNode, String location, ParseResult result) {
10931124
link.setParameters(getLinkParameters(parametersObject, location, result));
10941125
}
10951126

1127+
String requestBody = getString("requestBody",linkNode,false,location,result);
1128+
if (requestBody!= null) {
1129+
link.setRequestBody(requestBody);
1130+
}
1131+
10961132
ObjectNode headerObject = getObject("headers",linkNode,false,location,result);
10971133
if (headerObject!= null) {
10981134
link.setHeaders(getHeaders(headerObject, location, result));
@@ -1165,14 +1201,13 @@ public Callback getCallback(ObjectNode node,String location, ParseResult result)
11651201
JsonNode ref = node.get("$ref");
11661202
if (ref != null) {
11671203
if (ref.getNodeType().equals(JsonNodeType.STRING)) {
1168-
PathItem pathItem = new PathItem();
11691204
String mungedRef = mungedRef(ref.textValue());
11701205
if (mungedRef != null) {
1171-
pathItem.set$ref(mungedRef);
1206+
callback.set$ref(mungedRef);
11721207
}else{
1173-
pathItem.set$ref(ref.textValue());
1208+
callback.set$ref(ref.textValue());
11741209
}
1175-
return callback.addPathItem(name,pathItem);
1210+
return callback;
11761211
} else {
11771212
result.invalidType(location, "$ref", "string", node);
11781213
return null;
@@ -2498,7 +2533,7 @@ public Operation getOperation(ObjectNode obj, String location, ParseResult resul
24982533
if(docs != null) {
24992534
operation.setExternalDocs(docs);
25002535
}
2501-
value = getString("operationId", obj, false, location, result);
2536+
value = getString("operationId", obj, false, location, result, operationIDs);
25022537
if (StringUtils.isNotBlank(value)) {
25032538
operation.operationId(value);
25042539
}
@@ -2713,6 +2748,9 @@ protected static class ParseResult {
27132748
private Map<Location, JsonNode> unsupported = new LinkedHashMap<>();
27142749
private Map<Location, String> invalidType = new LinkedHashMap<>();
27152750
private List<Location> missing = new ArrayList<>();
2751+
private List<Location> warnings = new ArrayList<>();
2752+
private List<Location> unique = new ArrayList<>();
2753+
private List<Location> uniqueTags = new ArrayList<>();
27162754

27172755
public ParseResult() {
27182756
}
@@ -2728,6 +2766,17 @@ public void extra(String location, String key, JsonNode value) {
27282766
public void missing(String location, String key) {
27292767
missing.add(new Location(location, key));
27302768
}
2769+
2770+
public void warning(String location, String key) {
2771+
warnings.add(new Location(location, key));
2772+
}
2773+
2774+
public void unique(String location, String key) {
2775+
unique.add(new Location(location, key));
2776+
2777+
}
2778+
2779+
public void uniqueTags(String location, String key) {uniqueTags.add(new Location(location,key));}
27312780

27322781
public void invalidType(String location, String key, String expectedType, JsonNode value) {
27332782
invalidType.put(new Location(location, key), expectedType);
@@ -2758,11 +2807,26 @@ public List<String> getMessages() {
27582807
String message = "attribute " + location + l.key + " is missing";
27592808
messages.add(message);
27602809
}
2810+
for (Location l : warnings) {
2811+
String location = l.location.equals("") ? "" : l.location + ".";
2812+
String message = "attribute " + location +l.key;
2813+
messages.add(message);
2814+
}
27612815
for (Location l : unsupported.keySet()) {
27622816
String location = l.location.equals("") ? "" : l.location + ".";
27632817
String message = "attribute " + location + l.key + " is unsupported";
27642818
messages.add(message);
27652819
}
2820+
for (Location l : unique) {
2821+
String location = l.location.equals("") ? "" : l.location + ".";
2822+
String message = "attribute " + location + l.key + " is repeated";
2823+
messages.add(message);
2824+
}
2825+
for (Location l : uniqueTags) {
2826+
String location = l.location.equals("") ? "" : l.location + ".";
2827+
String message = "attribute " + location + l.key + " is repeated";
2828+
messages.add(message);
2829+
}
27662830
return messages;
27672831
}
27682832
}

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/RemoteUrl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ public void process(URLConnection connection) {
9494
public static String cleanUrl(String url) {
9595
String result = null;
9696
try {
97-
result =url.replaceAll("\\{", "%7B").replaceAll("\\}", "%7D");
97+
result =url.replaceAll("\\{", "%7B").
98+
replaceAll("\\}", "%7D").
99+
replaceAll(" ", "%20");
98100
}catch (Exception t){
99101
t.printStackTrace();
100102
}

0 commit comments

Comments
 (0)