in src/Microsoft.OpenApi/Models/OpenApiDocument.cs [115:253]
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();
}