/// <summary> /// Serialize <see cref="OpenApiDocument"/> to Open Api v2.0. /// </summary> public void SerializeAsV2(IOpenApiWriter writer) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } writer.WriteStartObject(); // swagger writer.WriteProperty(OpenApiConstants.Swagger, "2.0"); // info writer.WriteRequiredObject(OpenApiConstants.Info, Info, (w, i) => i.SerializeAsV2(w)); // host, basePath, schemes, consumes, produces WriteHostInfoV2(writer, Servers); // paths writer.WriteRequiredObject(OpenApiConstants.Paths, Paths, (w, p) => p.SerializeAsV2(w)); // definitions writer.WriteOptionalMap(OpenApiConstants.Definitions, Components?.Schemas, (w, s) => s.SerializeAsV2WithoutReference(w)); // parameters writer.WriteOptionalMap(OpenApiConstants.Parameters, Components?.Parameters, (w, p) => p.SerializeAsV2WithoutReference(w)); // responses writer.WriteOptionalMap(OpenApiConstants.Responses, Components?.Responses, (w, r) => r.SerializeAsV2WithoutReference(w)); // securityDefinitions writer.WriteOptionalMap(OpenApiConstants.SecurityDefinitions, Components?.SecuritySchemes, (w, s) => s.SerializeAsV2WithoutReference(w)); // security writer.WriteOptionalCollection( OpenApiConstants.Security, SecurityRequirements, (w, s) => s.SerializeAsV2(w)); // tags writer.WriteOptionalCollection(OpenApiConstants.Tags, Tags, (w, t) => t.SerializeAsV2WithoutReference(w)); // externalDocs writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, e) => e.SerializeAsV2(w)); // extensions writer.WriteExtensions(Extensions); writer.WriteEndObject(); }
/// <summary> /// Write Any object to the given writer. /// </summary> /// <param name="writer">The writer.</param> public virtual void Write(IOpenApiWriter writer) { if (writer == null) { throw Error.ArgumentNull("writer"); } // { for json, empty for YAML writer.WriteStartObject(); // write something after start WriteAfterStart(writer); // path items foreach (var item in this) { writer.WriteRequiredObject(item.Key, item.Value); } // write something before end. WriteBeforeEnd(writer); // } for json, empty for YAML writer.WriteEndObject(); }
/// <summary> /// Serialize <see cref="OpenApiOperation"/> to Open Api v3.0. /// </summary> public void SerializeAsV3(IOpenApiWriter writer) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } writer.WriteStartObject(); // tags writer.WriteOptionalCollection( OpenApiConstants.Tags, Tags, (w, t) => { t.SerializeAsV2(w); }); // summary writer.WriteProperty(OpenApiConstants.Summary, Summary); // description writer.WriteProperty(OpenApiConstants.Description, Description); // externalDocs writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, e) => e.SerializeAsV3(w)); // operationId writer.WriteProperty(OpenApiConstants.OperationId, OperationId); // parameters writer.WriteOptionalCollection(OpenApiConstants.Parameters, Parameters, (w, p) => p.SerializeAsV3(w)); // requestBody writer.WriteOptionalObject(OpenApiConstants.RequestBody, RequestBody, (w, r) => r.SerializeAsV3(w)); // responses writer.WriteRequiredObject(OpenApiConstants.Responses, Responses, (w, r) => r.SerializeAsV3(w)); // callbacks writer.WriteOptionalMap(OpenApiConstants.Callbacks, Callbacks, (w, c) => c.SerializeAsV3(w)); // deprecated writer.WriteProperty(OpenApiConstants.Deprecated, Deprecated, false); // security writer.WriteOptionalCollection(OpenApiConstants.Security, Security, (w, s) => s.SerializeAsV3(w)); // servers writer.WriteOptionalCollection(OpenApiConstants.Servers, Servers, (w, s) => s.SerializeAsV3(w)); // specification extensions writer.WriteExtensions(Extensions); writer.WriteEndObject(); }
/// <summary> /// Write Open API document to the given writer. /// </summary> /// <param name="writer">The writer.</param> public virtual void Write(IOpenApiWriter writer) { if (writer == null) { throw Error.ArgumentNull("writer"); } // { for json, empty for YAML writer.WriteStartObject(); // openapi:3.0.0 writer.WriteRequiredProperty(OpenApiConstants.OpenApiDocOpenApi, OpenApi.ToString()); // info writer.WriteRequiredObject(OpenApiConstants.OpenApiDocInfo, Info); // servers writer.WriteOptionalCollection(OpenApiConstants.OpenApiDocServers, Servers); // paths writer.WriteRequiredObject(OpenApiConstants.OpenApiDocPaths, Paths); // components writer.WriteOptionalObject(OpenApiConstants.OpenApiDocComponents, Components); // security writer.WriteOptionalCollection(OpenApiConstants.OpenApiDocSecurity, Security); // tags writer.WriteOptionalCollection(OpenApiConstants.OpenApiDocTags, Tags); // external docs writer.WriteOptionalObject(OpenApiConstants.OpenApiDocExternalDocs, ExternalDoc); // specification extensions writer.WriteDictionary(Extensions); // } for json, empty for YAML writer.WriteEndObject(); // flush writer.Flush(); }
/// <summary> /// Serialize <see cref="OpenApiDocument"/> to the latest patch of OpenAPI object V3.0. /// </summary> public void SerializeAsV3(IOpenApiWriter writer) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } writer.WriteStartObject(); // openapi writer.WriteProperty(OpenApiConstants.OpenApi, "3.0.1"); // info writer.WriteRequiredObject(OpenApiConstants.Info, Info, (w, i) => i.SerializeAsV3(w)); // servers writer.WriteOptionalCollection(OpenApiConstants.Servers, Servers, (w, s) => s.SerializeAsV3(w)); // paths writer.WriteRequiredObject(OpenApiConstants.Paths, Paths, (w, p) => p.SerializeAsV3(w)); // components writer.WriteOptionalObject(OpenApiConstants.Components, Components, (w, c) => c.SerializeAsV3(w)); // security writer.WriteOptionalCollection( OpenApiConstants.Security, SecurityRequirements, (w, s) => s.SerializeAsV3(w)); // tags writer.WriteOptionalCollection(OpenApiConstants.Tags, Tags, (w, t) => t.SerializeAsV3WithoutReference(w)); // external docs writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, e) => e.SerializeAsV3(w)); // extensions writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); writer.WriteEndObject(); }
/// <summary> /// Serialize to OpenAPI V3 document without using reference. /// </summary> public void SerializeAsV3WithoutReference(IOpenApiWriter writer) { writer.WriteStartObject(); // path items foreach (var item in PathItems) { writer.WriteRequiredObject(item.Key.Expression, item.Value, (w, p) => p.SerializeAsV3(w)); } // extensions writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_0); writer.WriteEndObject(); }
/// <summary> /// Serialize to Open Api v2.0 /// </summary> public void SerializeAsV2(IOpenApiWriter writer) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } writer.WriteStartObject(); foreach (var item in this) { writer.WriteRequiredObject(item.Key, item.Value, (w, p) => p.SerializeAsV2(w)); } writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi2_0); writer.WriteEndObject(); }
/// <summary> /// Write the optional Open API object/element. /// </summary> /// <typeparam name="T">The Open API element type. <see cref="IOpenApiElement"/></typeparam> /// <param name="writer">The Open API writer.</param> /// <param name="name">The property name.</param> /// <param name="value">The property value.</param> /// <param name="action">The proprety value writer action.</param> public static void WriteOptionalObject <T>( this IOpenApiWriter writer, string name, T value, Action <IOpenApiWriter, T> action) where T : IOpenApiElement { if (value != null) { var values = value as IEnumerable; if (values != null && !values.GetEnumerator().MoveNext()) { return; // Don't render optional empty collections } writer.WriteRequiredObject(name, value, action); } }
/// <summary> /// Serialize <see cref="OpenApiOperation"/> to Open Api v2.0. /// </summary> public void SerializeAsV2(IOpenApiWriter writer) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } writer.WriteStartObject(); // tags writer.WriteOptionalCollection( OpenApiConstants.Tags, Tags, (w, t) => { t.SerializeAsV3(w); }); // summary writer.WriteProperty(OpenApiConstants.Summary, Summary); // description writer.WriteProperty(OpenApiConstants.Description, Description); // externalDocs writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, e) => e.SerializeAsV2(w)); // operationId writer.WriteProperty(OpenApiConstants.OperationId, OperationId); IList <OpenApiParameter> parameters; if (Parameters == null) { parameters = new List <OpenApiParameter>(); } else { parameters = new List <OpenApiParameter>(Parameters); } if (RequestBody != null) { // consumes writer.WritePropertyName(OpenApiConstants.Consumes); writer.WriteStartArray(); var consumes = RequestBody.Content.Keys.Distinct().ToList(); foreach (var mediaType in consumes) { writer.WriteValue(mediaType); } writer.WriteEndArray(); // This is form data. We need to split the request body into multiple parameters. if (consumes.Contains("application/x-www-form-urlencoded") || consumes.Contains("multipart/form-data")) { foreach (var property in RequestBody.Content.First().Value.Schema.Properties) { parameters.Add( new OpenApiFormDataParameter { Description = property.Value.Description, Name = property.Key, Schema = property.Value, Required = RequestBody.Content.First().Value.Schema.Required.Contains(property.Key) }); } } else { var bodyParameter = new OpenApiBodyParameter { Description = RequestBody.Description, // V2 spec actually allows the body to have custom name. // Our library does not support this at the moment. Name = "body", Schema = RequestBody.Content.First().Value.Schema, Required = RequestBody.Required }; parameters.Add(bodyParameter); } } if (Responses != null) { var produces = Responses.Where(r => r.Value.Content != null) .SelectMany(r => r.Value.Content?.Keys) .Distinct() .ToList(); if (produces.Any()) { // produces writer.WritePropertyName(OpenApiConstants.Produces); writer.WriteStartArray(); foreach (var mediaType in produces) { writer.WriteValue(mediaType); } writer.WriteEndArray(); } } // parameters // Use the parameters created locally to include request body if exists. writer.WriteOptionalCollection(OpenApiConstants.Parameters, parameters, (w, p) => p.SerializeAsV2(w)); // responses writer.WriteRequiredObject(OpenApiConstants.Responses, Responses, (w, r) => r.SerializeAsV2(w)); // schemes // All schemes in the Servers are extracted, regardless of whether the host matches // the host defined in the outermost Swagger object. This is due to the // inaccessibility of information for that host in the context of an inner object like this Operation. if (Servers != null) { var schemes = Servers.Select( s => { Uri.TryCreate(s.Url, UriKind.RelativeOrAbsolute, out var url); return(url?.Scheme); }) .Where(s => s != null) .Distinct() .ToList(); writer.WriteOptionalCollection(OpenApiConstants.Schemes, schemes, (w, s) => w.WriteValue(s)); } // deprecated writer.WriteProperty(OpenApiConstants.Deprecated, Deprecated, false); // security writer.WriteOptionalCollection(OpenApiConstants.Security, Security, (w, s) => s.SerializeAsV2(w)); // specification extensions writer.WriteExtensions(Extensions); writer.WriteEndObject(); }
/// <summary> /// Serialize <see cref="OpenApiDocument"/> to OpenAPI object V2.0. /// </summary> public void SerializeAsV2(IOpenApiWriter writer) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } writer.WriteStartObject(); // swagger writer.WriteProperty(OpenApiConstants.Swagger, "2.0"); // info writer.WriteRequiredObject(OpenApiConstants.Info, Info, (w, i) => i.SerializeAsV2(w)); // host, basePath, schemes, consumes, produces WriteHostInfoV2(writer, Servers); // paths writer.WriteRequiredObject(OpenApiConstants.Paths, Paths, (w, p) => p.SerializeAsV2(w)); // Serialize each referenceable object as full object without reference if the reference in the object points to itself. // If the reference exists but points to other objects, the object is serialized to just that reference. // definitions writer.WriteOptionalMap( OpenApiConstants.Definitions, Components?.Schemas, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.Schema && component.Reference.Id == key) { component.SerializeAsV2WithoutReference(w); } else { component.SerializeAsV2(w); } }); // parameters writer.WriteOptionalMap( OpenApiConstants.Parameters, Components?.Parameters, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.Parameter && component.Reference.Id == key) { component.SerializeAsV2WithoutReference(w); } else { component.SerializeAsV2(w); } }); // responses writer.WriteOptionalMap( OpenApiConstants.Responses, Components?.Responses, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.Response && component.Reference.Id == key) { component.SerializeAsV2WithoutReference(w); } else { component.SerializeAsV2(w); } }); // securityDefinitions writer.WriteOptionalMap( OpenApiConstants.SecurityDefinitions, Components?.SecuritySchemes, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.SecurityScheme && component.Reference.Id == key) { component.SerializeAsV2WithoutReference(w); } else { component.SerializeAsV2(w); } }); // security writer.WriteOptionalCollection( OpenApiConstants.Security, SecurityRequirements, (w, s) => s.SerializeAsV2(w)); // tags writer.WriteOptionalCollection(OpenApiConstants.Tags, Tags, (w, t) => t.SerializeAsV2WithoutReference(w)); // externalDocs writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, e) => e.SerializeAsV2(w)); // extensions writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi2_0); writer.WriteEndObject(); }
/// <summary> /// Serialize <see cref="OpenApiDocument"/> to OpenAPI object V2.0. /// </summary> public void SerializeAsV2(IOpenApiWriter writer) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } writer.WriteStartObject(); // swagger writer.WriteProperty(OpenApiConstants.Swagger, "2.0"); // info writer.WriteRequiredObject(OpenApiConstants.Info, Info, (w, i) => i.SerializeAsV2(w)); // host, basePath, schemes, consumes, produces WriteHostInfoV2(writer, Servers); // paths writer.WriteRequiredObject(OpenApiConstants.Paths, Paths, (w, p) => p.SerializeAsV2(w)); // If references have been inlined we don't need the to render the components section // however if they have cycles, then we will need a component rendered if (writer.GetSettings().ReferenceInline != ReferenceInlineSetting.DoNotInlineReferences) { var loops = writer.GetSettings().LoopDetector.Loops; if (loops.TryGetValue(typeof(OpenApiSchema), out List <object> schemas)) { var openApiSchemas = schemas.Cast <OpenApiSchema>().Distinct().ToList() .ToDictionary <OpenApiSchema, string>(k => k.Reference.Id); foreach (var schema in openApiSchemas.Values.ToList()) { FindSchemaReferences.ResolveSchemas(Components, openApiSchemas); } writer.WriteOptionalMap( OpenApiConstants.Definitions, openApiSchemas, (w, key, component) => { component.SerializeAsV2WithoutReference(w); }); } } else { // Serialize each referenceable object as full object without reference if the reference in the object points to itself. // If the reference exists but points to other objects, the object is serialized to just that reference. // definitions writer.WriteOptionalMap( OpenApiConstants.Definitions, Components?.Schemas, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.Schema && component.Reference.Id == key) { component.SerializeAsV2WithoutReference(w); } else { component.SerializeAsV2(w); } }); } // parameters writer.WriteOptionalMap( OpenApiConstants.Parameters, Components?.Parameters, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.Parameter && component.Reference.Id == key) { component.SerializeAsV2WithoutReference(w); } else { component.SerializeAsV2(w); } }); // responses writer.WriteOptionalMap( OpenApiConstants.Responses, Components?.Responses, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.Response && component.Reference.Id == key) { component.SerializeAsV2WithoutReference(w); } else { component.SerializeAsV2(w); } }); // securityDefinitions writer.WriteOptionalMap( OpenApiConstants.SecurityDefinitions, Components?.SecuritySchemes, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.SecurityScheme && component.Reference.Id == key) { component.SerializeAsV2WithoutReference(w); } else { component.SerializeAsV2(w); } }); // security writer.WriteOptionalCollection( OpenApiConstants.Security, SecurityRequirements, (w, s) => s.SerializeAsV2(w)); // tags writer.WriteOptionalCollection(OpenApiConstants.Tags, Tags, (w, t) => t.SerializeAsV2WithoutReference(w)); // externalDocs writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, e) => e.SerializeAsV2(w)); // extensions writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi2_0); writer.WriteEndObject(); }
/// <summary> /// Serialize <see cref="OpenApiOperation"/> to Open Api v2.0. /// </summary> public void SerializeAsV2(IOpenApiWriter writer) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } writer.WriteStartObject(); // tags writer.WriteOptionalCollection( OpenApiConstants.Tags, Tags, (w, t) => { t.SerializeAsV3(w); }); // summary writer.WriteProperty(OpenApiConstants.Summary, Summary); // description writer.WriteProperty(OpenApiConstants.Description, Description); // externalDocs writer.WriteOptionalObject(OpenApiConstants.ExternalDocs, ExternalDocs, (w, e) => e.SerializeAsV2(w)); // operationId writer.WriteProperty(OpenApiConstants.OperationId, OperationId); IList <OpenApiParameter> parameters; if (Parameters == null) { parameters = new List <OpenApiParameter>(); } else { parameters = new List <OpenApiParameter>(Parameters); } if (RequestBody != null) { // consumes writer.WritePropertyName(OpenApiConstants.Consumes); writer.WriteStartArray(); var consumes = RequestBody.Content.Keys.Distinct().ToList(); foreach (var mediaType in consumes) { writer.WriteValue(mediaType); } writer.WriteEndArray(); // Create a parameter as BodyParameter type and add to Parameters. // This type will be used to populate the In property as "body" when Parameters is serialized. var bodyParameter = new BodyParameter { Description = RequestBody.Description, Schema = RequestBody.Content.First().Value.Schema, Format = new List <string>(consumes) }; parameters.Add(bodyParameter); } if (Responses != null) { var produces = Responses.Where(r => r.Value.Content != null) .SelectMany(r => r.Value.Content?.Keys) .Distinct() .ToList(); if (produces.Any()) { // produces writer.WritePropertyName(OpenApiConstants.Produces); writer.WriteStartArray(); foreach (var mediaType in produces) { writer.WriteValue(mediaType); } writer.WriteEndArray(); } } // parameters // Use the parameters created locally to include request body if exists. writer.WriteOptionalCollection(OpenApiConstants.Parameters, parameters, (w, p) => p.SerializeAsV2(w)); // responses writer.WriteRequiredObject(OpenApiConstants.Responses, Responses, (w, r) => r.SerializeAsV2(w)); // schemes // All schemes in the Servers are extracted, regardless of whether the host matches // the host defined in the outermost Swagger object. This is due to the // inaccessibility of information for that host in the context of an inner object like this Operation. if (Servers != null) { var schemes = Servers.Select( s => { Uri.TryCreate(s.Url, UriKind.RelativeOrAbsolute, out var url); return(url?.Scheme); }) .Where(s => s != null) .Distinct() .ToList(); writer.WriteOptionalCollection(OpenApiConstants.Schemes, schemes, (w, s) => w.WriteValue(s)); } // deprecated writer.WriteProperty(OpenApiConstants.Deprecated, Deprecated, false); // security writer.WriteOptionalCollection(OpenApiConstants.Security, Security, (w, s) => s.SerializeAsV2(w)); // specification extensions writer.WriteExtensions(Extensions); writer.WriteEndObject(); }