2
2
3
3
import com .fasterxml .jackson .databind .JsonNode ;
4
4
import com .fasterxml .jackson .databind .node .*;
5
+ import io .swagger .exception .RefException ;
5
6
import io .swagger .models .*;
7
+ import io .swagger .models .Path ;
6
8
import io .swagger .models .auth .*;
7
9
import io .swagger .models .parameters .*;
8
10
import io .swagger .models .properties .Property ;
9
11
import io .swagger .models .properties .PropertyBuilder ;
12
+ import io .swagger .models .refs .GenericRef ;
13
+ import io .swagger .models .refs .RefFormat ;
14
+ import io .swagger .models .refs .RefType ;
10
15
import io .swagger .util .Json ;
11
16
12
17
import java .util .*;
13
18
14
19
import static io .swagger .models .properties .PropertyBuilder .PropertyId .*;
20
+ import static io .swagger .parser .util .RefUtils .isAnExternalRefFormat ;
15
21
16
22
public class SwaggerDeserializer {
17
23
static Set <String > ROOT_KEYS = new HashSet <String >(Arrays .asList ("swagger" , "info" , "host" , "basePath" , "schemes" , "consumes" , "produces" , "paths" , "definitions" , "parameters" , "responses" , "securityDefinitions" , "security" , "tags" , "externalDocs" ));
@@ -29,17 +35,17 @@ public class SwaggerDeserializer {
29
35
static Set <String > BODY_PARAMETER_KEYS = new HashSet <String >(Arrays .asList ("name" , "in" , "description" , "required" , "schema" ));
30
36
static Set <String > SECURITY_SCHEME_KEYS = new HashSet <String >(Arrays .asList ("type" , "name" , "in" , "description" , "flow" , "authorizationUrl" , "tokenUrl" , "scopes" ));
31
37
32
- public SwaggerDeserializationResult deserialize (JsonNode rootNode ) {
38
+ public SwaggerDeserializationResult deserialize (JsonNode rootNode , String parentFileLocation ) {
33
39
SwaggerDeserializationResult result = new SwaggerDeserializationResult ();
34
40
ParseResult rootParse = new ParseResult ();
35
41
36
- Swagger swagger = parseRoot (rootNode , rootParse );
42
+ Swagger swagger = parseRoot (rootNode , rootParse , parentFileLocation );
37
43
result .setSwagger (swagger );
38
44
result .setMessages (rootParse .getMessages ());
39
45
return result ;
40
46
}
41
47
42
- public Swagger parseRoot (JsonNode node , ParseResult result ) {
48
+ public Swagger parseRoot (JsonNode node , ParseResult result , String parentFileLocation ) {
43
49
String location = "" ;
44
50
Swagger swagger = new Swagger ();
45
51
if (node .getNodeType ().equals (JsonNodeType .OBJECT )) {
@@ -50,7 +56,7 @@ public Swagger parseRoot(JsonNode node, ParseResult result) {
50
56
String value = getString ("swagger" , on , true , location , result );
51
57
swagger .setSwagger (value );
52
58
53
- ObjectNode obj = getObject ("info" , on , true , "" , result );
59
+ ObjectNode obj = getRootObject ("info" , on , true , "" , result , parentFileLocation );
54
60
if (obj != null ) {
55
61
Info info = info (obj , "info" , result );
56
62
swagger .info (info );
@@ -102,15 +108,15 @@ public Swagger parseRoot(JsonNode node, ParseResult result) {
102
108
}
103
109
}
104
110
105
- obj = getObject ("paths" , on , true , location , result );
111
+ obj = getRootObject ("paths" , on , true , location , result , parentFileLocation );
106
112
Map <String , Path > paths = paths (obj , "paths" , result );
107
113
swagger .paths (paths );
108
114
109
- obj = getObject ("definitions" , on , false , location , result );
115
+ obj = getRootObject ("definitions" , on , false , location , result , parentFileLocation );
110
116
Map <String , Model > definitions = definitions (obj , "definitions" , result );
111
117
swagger .setDefinitions (definitions );
112
118
113
- obj = getObject ("parameters" , on , false , location , result );
119
+ obj = getRootObject ("parameters" , on , false , location , result , parentFileLocation );
114
120
// TODO: parse
115
121
116
122
if (obj != null ) {
@@ -126,11 +132,11 @@ public Swagger parseRoot(JsonNode node, ParseResult result) {
126
132
swagger .setParameters (parameters );
127
133
}
128
134
129
- obj = getObject ("responses" , on , false , location , result );
135
+ obj = getRootObject ("responses" , on , false , location , result , parentFileLocation );
130
136
Map <String , Response > responses = responses (obj , "responses" , result );
131
137
swagger .responses (responses );
132
138
133
- obj = getObject ("securityDefinitions" , on , false , location , result );
139
+ obj = getRootObject ("securityDefinitions" , on , false , location , result , parentFileLocation );
134
140
Map <String , SecuritySchemeDefinition > securityDefinitions = securityDefinitions (obj , location , result );
135
141
swagger .setSecurityDefinitions (securityDefinitions );
136
142
@@ -142,7 +148,7 @@ public Swagger parseRoot(JsonNode node, ParseResult result) {
142
148
List <Tag > tags = tags (array , location , result );
143
149
swagger .tags (tags );
144
150
145
- obj = getObject ("externalDocs" , on , false , location , result );
151
+ obj = getRootObject ("externalDocs" , on , false , location , result , parentFileLocation );
146
152
ExternalDocs docs = externalDocs (obj , location , result );
147
153
swagger .externalDocs (docs );
148
154
@@ -1378,6 +1384,52 @@ else if(!value.getNodeType().equals(JsonNodeType.OBJECT)) {
1378
1384
return on ;
1379
1385
}
1380
1386
1387
+ private void changeInternalRefsToRelative (ObjectNode node , String file ) {
1388
+ if (node != null && node .has ("$ref" )) {
1389
+ String $ref = node .get ("$ref" ).asText ();
1390
+ GenericRef ref = new GenericRef (RefType .DEFINITION , $ref );
1391
+ if (ref .getFormat () == RefFormat .INTERNAL ) {
1392
+ node .put ("$ref" , file + $ref );
1393
+ }
1394
+ }
1395
+ Iterator <JsonNode > it = node .iterator ();
1396
+ while (it .hasNext ()) {
1397
+ JsonNode child = it .next ();
1398
+ if (child .getNodeType ().equals (JsonNodeType .OBJECT )) {
1399
+ changeInternalRefsToRelative ((ObjectNode ) child , file );
1400
+ }
1401
+ }
1402
+ }
1403
+
1404
+ public ObjectNode getRootObject (String key , ObjectNode node , boolean required , String location , ParseResult result , String parentFileLocation ) {
1405
+ ObjectNode on = getObject (key , node , required , location , result );
1406
+ while (on != null && on .has ("$ref" )) {
1407
+ String ref = on .get ("$ref" ).asText ();
1408
+ String [] refParts = ref .split ("#/" );
1409
+ String file = refParts [0 ];
1410
+ String definitionPath = refParts .length == 2 ? refParts [1 ] : null ;
1411
+ java .nio .file .Path parentDirectory = PathUtils .getParentDirectoryOfFile (parentFileLocation );
1412
+ String contents = RefUtils .readExternalRef (file , RefFormat .RELATIVE , null , parentDirectory );
1413
+
1414
+ if (definitionPath == null ) {
1415
+ on = DeserializationUtils .deserialize (contents , file , ObjectNode .class );
1416
+ } else {
1417
+ JsonNode tree = DeserializationUtils .deserializeIntoTree (contents , file );
1418
+
1419
+ String [] jsonPathElements = definitionPath .split ("/" );
1420
+ for (String jsonPathElement : jsonPathElements ) {
1421
+ tree = tree .get (jsonPathElement );
1422
+ if (tree == null ) {
1423
+ throw new RefException (definitionPath , file );
1424
+ }
1425
+ }
1426
+ on = DeserializationUtils .deserialize (tree , file , ObjectNode .class );
1427
+ changeInternalRefsToRelative (on , file );
1428
+ }
1429
+ }
1430
+ return on ;
1431
+ }
1432
+
1381
1433
public Double getDouble (String key , ObjectNode node , boolean required , String location , ParseResult result ) {
1382
1434
Double value = null ;
1383
1435
JsonNode v = node .get (key );
0 commit comments