private SwaggerObjectBase Build(JToken token) { var jObject = token as JObject; if (jObject != null) { JToken referenceToken; // Only one $ref is allowed inside a swagger JObject if (jObject.TryGetValue("$ref", out referenceToken)) { if (referenceToken.Type != JTokenType.String && referenceToken.Type != JTokenType.Null) { throw new JsonException($"JSON reference $ref property must have a string or null value, instead of {referenceToken.Type}, location: {referenceToken.Path}."); } SwaggerReferenceObject deferredObject = new SwaggerReferenceObject(); var formatted = RestApiHelper.FormatReferenceFullPath((string)referenceToken); deferredObject.DeferredReference = formatted.Item1; deferredObject.ReferenceName = formatted.Item2; // For swagger, other properties are still allowed besides $ref, e.g. // "schema": { // "$ref": "#/defintions/foo" // "example": { } // } // Use Token property to keep other properties // These properties cannot be referenced jObject.Remove("$ref"); deferredObject.Token = jObject; return(deferredObject); } else { string location = GetLocation(token); SwaggerObject existingObject; if (_documentObjectCache.TryGetValue(location, out existingObject)) { return(existingObject); } var swaggerObject = new SwaggerObject { Location = location }; foreach (KeyValuePair <string, JToken> property in jObject) { swaggerObject.Dictionary.Add(property.Key, Build(property.Value)); } _documentObjectCache.Add(location, swaggerObject); return(swaggerObject); } } var jArray = token as JArray; if (jArray != null) { var swaggerArray = new SwaggerArray(); foreach (var property in jArray) { swaggerArray.Array.Add(Build(property)); } return(swaggerArray); } return(new SwaggerValue { Token = token }); }
private SwaggerObjectBase Build(JToken token, string swaggerDir) { // Fetch from cache first var location = GetLocation(token); SwaggerObjectBase existingObject; if (_documentObjectCache.TryGetValue(location, out existingObject)) { return(existingObject); } var jObject = token as JObject; if (jObject != null) { // Only one $ref is allowed inside a swagger JObject JToken referenceToken; if (jObject.TryGetValue(ReferenceKey, out referenceToken)) { if (referenceToken.Type != JTokenType.String && referenceToken.Type != JTokenType.Null) { throw new JsonException($"JSON reference $ref property must have a string or null value, instead of {referenceToken.Type}, location: {referenceToken.Path}."); } var swaggerReference = RestApiHelper.FormatReferenceFullPath((string)referenceToken); switch (swaggerReference.Type) { case SwaggerFormattedReferenceType.InternalReference: var deferredObject = new SwaggerReferenceObject { DeferredReference = swaggerReference.Path, ReferenceName = swaggerReference.Name, Location = location }; // For swagger, other properties are still allowed besides $ref, e.g. // "schema": { // "$ref": "#/definitions/foo" // "example": { } // } // Use Token property to keep other properties // These properties cannot be referenced jObject.Remove("$ref"); deferredObject.Token = jObject; _documentObjectCache.Add(location, deferredObject); return(deferredObject); case SwaggerFormattedReferenceType.ExternalReference: jObject.Remove("$ref"); var externalJObject = LoadExternalReference(Path.Combine(swaggerDir, swaggerReference.Path)); RestApiHelper.CheckSpecificKey(externalJObject, ReferenceKey, () => { throw new DocfxException($"{ReferenceKey} in {swaggerReference.Path} is not supported in external reference currently."); }); foreach (var item in externalJObject) { JToken value; if (jObject.TryGetValue(item.Key, out value)) { Logger.LogWarning($"{item.Key} inside {jObject.Path} would be overwritten by the value of same key inside {swaggerReference.Path} with path {externalJObject.Path}."); } jObject[item.Key] = item.Value; } return(new SwaggerValue { Location = location, Token = jObject }); default: throw new DocfxException($"{referenceToken} does not support type {swaggerReference.Type}."); } } var swaggerObject = new SwaggerObject { Location = location }; foreach (KeyValuePair <string, JToken> property in jObject) { swaggerObject.Dictionary.Add(property.Key, Build(property.Value, swaggerDir)); } _documentObjectCache.Add(location, swaggerObject); return(swaggerObject); } var jArray = token as JArray; if (jArray != null) { var swaggerArray = new SwaggerArray { Location = location }; foreach (var property in jArray) { swaggerArray.Array.Add(Build(property, swaggerDir)); } return(swaggerArray); } return(new SwaggerValue { Location = location, Token = token }); }
private SwaggerObjectBase LoadCore(JToken token, string swaggerPath, bool isExample = false) { // Fetch from cache first var location = JsonLocationHelper.GetLocation(token); var jsonLocationInfo = new JsonLocationInfo(swaggerPath, location); if (_documentObjectCache.TryGetValue(jsonLocationInfo, out SwaggerObjectBase existingObject)) { return(existingObject); } if (token is JObject jObject) { // Only one $ref is allowed inside a swagger JObject if (jObject.TryGetValue(ReferenceKey, out JToken referenceToken) && !isExample) { if (referenceToken.Type != JTokenType.String && referenceToken.Type != JTokenType.Null) { throw new JsonException($"JSON reference $ref property must have a string or null value, instead of {referenceToken.Type}, location: {referenceToken.Path}."); } var swaggerReference = RestApiHelper.FormatReferenceFullPath((string)referenceToken); switch (swaggerReference.Type) { case SwaggerFormattedReferenceType.InternalReference: var deferredObject = new SwaggerReferenceObject { DeferredReference = swaggerReference.Path, ReferenceName = swaggerReference.Name, Location = location }; // For swagger, other properties are still allowed besides $ref, e.g. // "schema": { // "$ref": "#/definitions/foo" // "example": { } // } // Use Token property to keep other properties // These properties cannot be referenced jObject.Remove("$ref"); deferredObject.Token = jObject; _documentObjectCache.Add(jsonLocationInfo, deferredObject); return(deferredObject); case SwaggerFormattedReferenceType.ExternalReference: jObject.Remove("$ref"); var externalJObject = LoadExternalReference(Path.Combine(Path.GetDirectoryName(swaggerPath), swaggerReference.ExternalFilePath)); RestApiHelper.CheckSpecificKey(externalJObject, ReferenceKey, () => { throw new DocfxException($"{ReferenceKey} in {swaggerReference.ExternalFilePath} is not supported in external reference currently."); }); foreach (var item in externalJObject) { if (jObject.TryGetValue(item.Key, out JToken value)) { Logger.LogWarning($"{item.Key} inside {jObject.Path} would be overwritten by the value of same key inside {swaggerReference.ExternalFilePath} with path {externalJObject.Path}."); } jObject[item.Key] = item.Value; } var resolved = new SwaggerValue { Location = location, Token = jObject }; _documentObjectCache.Add(jsonLocationInfo, resolved); return(resolved); case SwaggerFormattedReferenceType.ExternalEmbeddedReference: // Defer resolving external reference to resolve step, to prevent loop reference. var externalDeferredObject = new SwaggerReferenceObject { ExternalFilePath = Path.Combine(Path.GetDirectoryName(swaggerPath), swaggerReference.ExternalFilePath), DeferredReference = swaggerReference.Path, ReferenceName = swaggerReference.Name, Location = location }; jObject.Remove("$ref"); externalDeferredObject.Token = jObject; _documentObjectCache.Add(jsonLocationInfo, externalDeferredObject); return(externalDeferredObject); default: throw new DocfxException($"{referenceToken} does not support type {swaggerReference.Type}."); } } var swaggerObject = new SwaggerObject { Location = location }; foreach (KeyValuePair <string, JToken> property in jObject) { swaggerObject.Dictionary.Add(property.Key, LoadCore(property.Value, swaggerPath, isExample || IsExampleProperty(property.Key, jObject?.Parent?.Parent?.Path))); } _documentObjectCache.Add(jsonLocationInfo, swaggerObject); return(swaggerObject); } if (token is JArray jArray) { var swaggerArray = new SwaggerArray { Location = location }; foreach (var property in jArray) { swaggerArray.Array.Add(LoadCore(property, swaggerPath, isExample)); } return(swaggerArray); } return(new SwaggerValue { Location = location, Token = token }); }
private SwaggerObjectBase Build(JToken token) { // Fetch from cache first var location = GetLocation(token); SwaggerObjectBase existingObject; if (_documentObjectCache.TryGetValue(location, out existingObject)) { return existingObject; } var jObject = token as JObject; if (jObject != null) { // Only one $ref is allowed inside a swagger JObject JToken referenceToken; if (jObject.TryGetValue("$ref", out referenceToken)) { if (referenceToken.Type != JTokenType.String && referenceToken.Type != JTokenType.Null) { throw new JsonException($"JSON reference $ref property must have a string or null value, instead of {referenceToken.Type}, location: {referenceToken.Path}."); } var formatted = RestApiHelper.FormatReferenceFullPath((string)referenceToken); var deferredObject = new SwaggerReferenceObject { DeferredReference = formatted.Item1, ReferenceName = formatted.Item2, Location = location }; // For swagger, other properties are still allowed besides $ref, e.g. // "schema": { // "$ref": "#/definitions/foo" // "example": { } // } // Use Token property to keep other properties // These properties cannot be referenced jObject.Remove("$ref"); deferredObject.Token = jObject; _documentObjectCache.Add(location, deferredObject); return deferredObject; } var swaggerObject = new SwaggerObject { Location = location }; foreach (KeyValuePair<string, JToken> property in jObject) { swaggerObject.Dictionary.Add(property.Key, Build(property.Value)); } _documentObjectCache.Add(location, swaggerObject); return swaggerObject; } var jArray = token as JArray; if (jArray != null) { var swaggerArray = new SwaggerArray { Location = location }; foreach (var property in jArray) { swaggerArray.Array.Add(Build(property)); } return swaggerArray; } return new SwaggerValue { Location = location, Token = token }; }