in src/Microsoft.OpenApi/Models/OpenApiOperation.cs [172:330]
public void SerializeAsV2(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.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)
{
var paramName = property.Key;
var paramSchema = property.Value;
if (paramSchema.Type == "string" && paramSchema.Format == "binary") {
paramSchema.Type = "file";
paramSchema.Format = null;
}
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 content = RequestBody.Content.Values.FirstOrDefault();
var bodyParameter = new OpenApiBodyParameter
{
Description = RequestBody.Description,
// V2 spec actually allows the body to have custom name.
// To allow round-tripping we use an extension to hold the name
Name = "body",
Schema = content?.Schema ?? new OpenApiSchema(),
Required = RequestBody.Required,
Extensions = RequestBody.Extensions.ToDictionary(k => k.Key, v => v.Value) // Clone extensions so we can remove the x-bodyName extensions from the output V2 model.
};
if (bodyParameter.Extensions.ContainsKey(OpenApiConstants.BodyName))
{
bodyParameter.Name = (RequestBody.Extensions[OpenApiConstants.BodyName] as OpenApiString)?.Value ?? "body";
bodyParameter.Extensions.Remove(OpenApiConstants.BodyName);
}
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, OpenApiSpecVersion.OpenApi2_0);
writer.WriteEndObject();
}