/// <summary> /// Serialize <see cref="OpenApiSchema"/> to Open Api v3.0 /// </summary> public void SerializeAsV3(IOpenApiWriter writer) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } var settings = writer.GetSettings(); if (Reference != null) { if (settings.ReferenceInline != ReferenceInlineSetting.InlineLocalReferences) { Reference.SerializeAsV3(writer); return; } // If Loop is detected then just Serialize as a reference. if (!settings.LoopDetector.PushLoop <OpenApiSchema>(this)) { settings.LoopDetector.SaveLoop(this); Reference.SerializeAsV3(writer); return; } } SerializeAsV3WithoutReference(writer); if (Reference != null) { settings.LoopDetector.PopLoop <OpenApiSchema>(); } }
/// <summary> /// Serialize <see cref="OpenApiExample"/> to Open Api v3.0 /// </summary> public void SerializeAsV3(IOpenApiWriter writer) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } if (Reference != null && writer.GetSettings().ReferenceInline != ReferenceInlineSetting.InlineLocalReferences) { Reference.SerializeAsV3(writer); return; } SerializeAsV3WithoutReference(writer); }
/// <summary> /// Serialize <see cref="OpenApiSchema"/> to Open Api v2.0 and handles not marking the provided property /// as readonly if its included in the provided list of required properties of parent schema. /// </summary> /// <param name="writer">The open api writer.</param> /// <param name="parentRequiredProperties">The list of required properties in parent schema.</param> /// <param name="propertyName">The property name that will be serialized.</param> internal void SerializeAsV2( IOpenApiWriter writer, ISet <string> parentRequiredProperties, string propertyName) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } if (Reference != null) { var settings = writer.GetSettings(); if (settings.ReferenceInline != ReferenceInlineSetting.InlineLocalReferences) { Reference.SerializeAsV2(writer); return; } // If Loop is detected then just Serialize as a reference. if (!settings.LoopDetector.PushLoop <OpenApiSchema>(this)) { settings.LoopDetector.SaveLoop(this); Reference.SerializeAsV2(writer); return; } } if (parentRequiredProperties == null) { parentRequiredProperties = new HashSet <string>(); } SerializeAsV2WithoutReference(writer, parentRequiredProperties, propertyName); }
/// <summary> /// Serialize <see cref="OpenApiComponents"/> to Open Api v3.0. /// </summary> public void SerializeAsV3(IOpenApiWriter writer) { if (writer == null) { throw Error.ArgumentNull(nameof(writer)); } // 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; writer.WriteStartObject(); if (loops.TryGetValue(typeof(OpenApiSchema), out List <object> schemas)) { var openApiSchemas = schemas.Cast <OpenApiSchema>().Distinct().ToList() .ToDictionary <OpenApiSchema, string>(k => k.Reference.Id); writer.WriteOptionalMap( OpenApiConstants.Schemas, Schemas, (w, key, component) => { component.SerializeAsV3WithoutReference(w); }); } writer.WriteEndObject(); return; } writer.WriteStartObject(); // 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. // schemas writer.WriteOptionalMap( OpenApiConstants.Schemas, Schemas, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.Schema && component.Reference.Id == key) { component.SerializeAsV3WithoutReference(w); } else { component.SerializeAsV3(w); } }); // responses writer.WriteOptionalMap( OpenApiConstants.Responses, Responses, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.Response && component.Reference.Id == key) { component.SerializeAsV3WithoutReference(w); } else { component.SerializeAsV3(w); } }); // parameters writer.WriteOptionalMap( OpenApiConstants.Parameters, Parameters, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.Parameter && component.Reference.Id == key) { component.SerializeAsV3WithoutReference(w); } else { component.SerializeAsV3(w); } }); // examples writer.WriteOptionalMap( OpenApiConstants.Examples, Examples, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.Example && component.Reference.Id == key) { component.SerializeAsV3WithoutReference(w); } else { component.SerializeAsV3(w); } }); // requestBodies writer.WriteOptionalMap( OpenApiConstants.RequestBodies, RequestBodies, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.RequestBody && component.Reference.Id == key) { component.SerializeAsV3WithoutReference(w); } else { component.SerializeAsV3(w); } }); // headers writer.WriteOptionalMap( OpenApiConstants.Headers, Headers, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.Header && component.Reference.Id == key) { component.SerializeAsV3WithoutReference(w); } else { component.SerializeAsV3(w); } }); // securitySchemes writer.WriteOptionalMap( OpenApiConstants.SecuritySchemes, SecuritySchemes, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.SecurityScheme && component.Reference.Id == key) { component.SerializeAsV3WithoutReference(w); } else { component.SerializeAsV3(w); } }); // links writer.WriteOptionalMap( OpenApiConstants.Links, Links, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.Link && component.Reference.Id == key) { component.SerializeAsV3WithoutReference(w); } else { component.SerializeAsV3(w); } }); // callbacks writer.WriteOptionalMap( OpenApiConstants.Callbacks, Callbacks, (w, key, component) => { if (component.Reference != null && component.Reference.Type == ReferenceType.Callback && component.Reference.Id == key) { component.SerializeAsV3WithoutReference(w); } else { component.SerializeAsV3(w); } }); // extensions writer.WriteExtensions(Extensions, OpenApiSpecVersion.OpenApi3_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(); }