@@ -90,6 +90,7 @@ public class OpenAPIDeserializer {
90
90
private static final String PATH_PARAMETER = "path" ;
91
91
private static final String HEADER_PARAMETER = "header" ;
92
92
93
+ private final Set <String > operationIDs = new HashSet <>();
93
94
94
95
public SwaggerParseResult deserialize (JsonNode rootNode ) {
95
96
return deserialize (rootNode , null );
@@ -292,11 +293,18 @@ public List<Tag> getTagList(ArrayNode obj, String location, ParseResult result)
292
293
return null ;
293
294
}
294
295
List <Tag > tags = new ArrayList <>();
296
+ Set <String > tagsTracker = new HashSet <>();
295
297
for (JsonNode item : obj ) {
296
298
if (item .getNodeType ().equals (JsonNodeType .OBJECT )) {
297
299
Tag tag = getTag ((ObjectNode ) item , location , result );
298
300
if (tag != null ) {
299
301
tags .add (tag );
302
+
303
+ if (tagsTracker .contains ((String )tag .getName ())) {
304
+ result .uniqueTags (location ,tag .getName ());
305
+ }
306
+
307
+ tagsTracker .add (tag .getName ());
300
308
}
301
309
}
302
310
}
@@ -516,6 +524,9 @@ public Paths getPaths(ObjectNode obj, String location, ParseResult result) {
516
524
if (!pathValue .getNodeType ().equals (JsonNodeType .OBJECT )) {
517
525
result .invalidType (location , pathName , "object" , pathValue );
518
526
} else {
527
+ if (!pathName .startsWith ("/" )){
528
+ result .warning (location ," Resource " +pathName + " should start with /" );
529
+ }
519
530
ObjectNode path = (ObjectNode ) pathValue ;
520
531
PathItem pathObj = getPathItem (path ,String .format ("%s.'%s'" , location ,pathName ), result );
521
532
String [] eachPart = pathName .split ("/" );
@@ -730,7 +741,7 @@ public ExternalDocumentation getExternalDocs(ObjectNode node, String location, P
730
741
}
731
742
732
743
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 ) {
734
745
String value = null ;
735
746
JsonNode v = node .get (key );
736
747
if (node == null || v == null ) {
@@ -742,10 +753,18 @@ public String getString(String key, ObjectNode node, boolean required, String lo
742
753
result .invalidType (location , key , "string" , node );
743
754
} else {
744
755
value = v .asText ();
756
+ if (uniqueValues != null && !uniqueValues .add (value )) {
757
+ result .unique (location , "operationId" );
758
+ result .invalid ();
759
+ }
745
760
}
746
761
return value ;
747
762
}
748
763
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
+
749
768
public Set <String > getKeys (ObjectNode node ) {
750
769
Set <String > keys = new LinkedHashSet <>();
751
770
if (node == null ) {
@@ -845,6 +864,12 @@ public License getLicense(ObjectNode node, String location, ParseResult result)
845
864
846
865
value = getString ("url" , node , false , location , result );
847
866
if (StringUtils .isNotBlank (value )) {
867
+ try {
868
+ new URL (value );
869
+ }
870
+ catch (Exception e ) {
871
+ result .warning (location ,value );
872
+ }
848
873
license .setUrl (value );
849
874
}
850
875
@@ -876,6 +901,12 @@ public Contact getContact(ObjectNode node, String location, ParseResult result)
876
901
877
902
value = getString ("url" , node , false , location , result );
878
903
if (StringUtils .isNotBlank (value )) {
904
+ try {
905
+ new URL (value );
906
+ }
907
+ catch (Exception e ) {
908
+ result .warning (location ,value );
909
+ }
879
910
contact .setUrl (value );
880
911
}
881
912
@@ -1093,6 +1124,11 @@ public Link getLink(ObjectNode linkNode, String location, ParseResult result) {
1093
1124
link .setParameters (getLinkParameters (parametersObject , location , result ));
1094
1125
}
1095
1126
1127
+ String requestBody = getString ("requestBody" ,linkNode ,false ,location ,result );
1128
+ if (requestBody != null ) {
1129
+ link .setRequestBody (requestBody );
1130
+ }
1131
+
1096
1132
ObjectNode headerObject = getObject ("headers" ,linkNode ,false ,location ,result );
1097
1133
if (headerObject != null ) {
1098
1134
link .setHeaders (getHeaders (headerObject , location , result ));
@@ -1165,14 +1201,13 @@ public Callback getCallback(ObjectNode node,String location, ParseResult result)
1165
1201
JsonNode ref = node .get ("$ref" );
1166
1202
if (ref != null ) {
1167
1203
if (ref .getNodeType ().equals (JsonNodeType .STRING )) {
1168
- PathItem pathItem = new PathItem ();
1169
1204
String mungedRef = mungedRef (ref .textValue ());
1170
1205
if (mungedRef != null ) {
1171
- pathItem .set$ref (mungedRef );
1206
+ callback .set$ref (mungedRef );
1172
1207
}else {
1173
- pathItem .set$ref (ref .textValue ());
1208
+ callback .set$ref (ref .textValue ());
1174
1209
}
1175
- return callback . addPathItem ( name , pathItem ) ;
1210
+ return callback ;
1176
1211
} else {
1177
1212
result .invalidType (location , "$ref" , "string" , node );
1178
1213
return null ;
@@ -2498,7 +2533,7 @@ public Operation getOperation(ObjectNode obj, String location, ParseResult resul
2498
2533
if (docs != null ) {
2499
2534
operation .setExternalDocs (docs );
2500
2535
}
2501
- value = getString ("operationId" , obj , false , location , result );
2536
+ value = getString ("operationId" , obj , false , location , result , operationIDs );
2502
2537
if (StringUtils .isNotBlank (value )) {
2503
2538
operation .operationId (value );
2504
2539
}
@@ -2713,6 +2748,9 @@ protected static class ParseResult {
2713
2748
private Map <Location , JsonNode > unsupported = new LinkedHashMap <>();
2714
2749
private Map <Location , String > invalidType = new LinkedHashMap <>();
2715
2750
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 <>();
2716
2754
2717
2755
public ParseResult () {
2718
2756
}
@@ -2728,6 +2766,17 @@ public void extra(String location, String key, JsonNode value) {
2728
2766
public void missing (String location , String key ) {
2729
2767
missing .add (new Location (location , key ));
2730
2768
}
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 ));}
2731
2780
2732
2781
public void invalidType (String location , String key , String expectedType , JsonNode value ) {
2733
2782
invalidType .put (new Location (location , key ), expectedType );
@@ -2758,11 +2807,26 @@ public List<String> getMessages() {
2758
2807
String message = "attribute " + location + l .key + " is missing" ;
2759
2808
messages .add (message );
2760
2809
}
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
+ }
2761
2815
for (Location l : unsupported .keySet ()) {
2762
2816
String location = l .location .equals ("" ) ? "" : l .location + "." ;
2763
2817
String message = "attribute " + location + l .key + " is unsupported" ;
2764
2818
messages .add (message );
2765
2819
}
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
+ }
2766
2830
return messages ;
2767
2831
}
2768
2832
}
0 commit comments