diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 1ce80f092..047062874 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -283,7 +283,7 @@ public void SerializeAsV2(IOpenApiWriter writer) { foreach (var requestBody in Components.RequestBodies.Where(b => !parameters.ContainsKey(b.Key))) { - parameters.Add(requestBody.Key, requestBody.Value.ConvertToBodyParameter()); + parameters.Add(requestBody.Key, requestBody.Value.ConvertToBodyParameter(writer)); } } writer.WriteOptionalMap( diff --git a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs index efd586e80..7e3b5d712 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs @@ -212,7 +212,7 @@ private void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version /// public void SerializeAsV2(IOpenApiWriter writer) { - Utils.CheckArgumentNull(writer);; + Utils.CheckArgumentNull(writer); writer.WriteStartObject(); @@ -258,7 +258,7 @@ public void SerializeAsV2(IOpenApiWriter writer) } else { - parameters.Add(RequestBody.ConvertToBodyParameter()); + parameters.Add(RequestBody.ConvertToBodyParameter(writer)); } } else if (RequestBody.Reference != null && RequestBody.Reference.HostDocument is {} hostDocument) diff --git a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs index 037e7d92c..0fb16471f 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs @@ -112,7 +112,7 @@ public void SerializeAsV2(IOpenApiWriter writer) // RequestBody object does not exist in V2. } - internal OpenApiBodyParameter ConvertToBodyParameter() + internal virtual OpenApiParameter ConvertToBodyParameter(IOpenApiWriter writer) { var bodyParameter = new OpenApiBodyParameter { diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs index 598d70310..59fb27724 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs @@ -92,7 +92,6 @@ public override void SerializeAsV3(IOpenApiWriter writer) if (!writer.GetSettings().ShouldInlineReference(_reference)) { _reference.SerializeAsV3(writer); - return; } else { @@ -106,7 +105,6 @@ public override void SerializeAsV31(IOpenApiWriter writer) if (!writer.GetSettings().ShouldInlineReference(_reference)) { _reference.SerializeAsV31(writer); - return; } else { @@ -121,5 +119,18 @@ private void SerializeInternal(IOpenApiWriter writer, Utils.CheckArgumentNull(writer); action(writer, Target); } + + /// + internal override OpenApiParameter ConvertToBodyParameter(IOpenApiWriter writer) + { + if (writer.GetSettings().ShouldInlineReference(_reference)) + { + return Target.ConvertToBodyParameter(writer); + } + else + { + return new OpenApiParameterReference(_reference.Id, _reference.HostDocument); + } + } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs index 7c76c424c..1d7fd39d3 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs @@ -10,6 +10,7 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Reader.V2; using Microsoft.OpenApi.Reader.V3; @@ -507,5 +508,99 @@ public async Task LoadV3ExamplesInRequestBodyParameterAsExtensionsWorks() expected = expected.MakeLineBreaksEnvironmentNeutral(); Assert.Equal(expected, actual); } + [Fact] + public async Task SerializesBodyReferencesWorks() + { + var openApiDocument = new OpenApiDocument(); + + var operation = new OpenApiOperation + { + RequestBody = new OpenApiRequestBodyReference("UserRequest", openApiDocument) + { + Description = "User request body" + } + }; + openApiDocument.Paths.Add("/users", new OpenApiPathItem + { + Operations = new Dictionary + { + [OperationType.Post] = operation + } + }); + openApiDocument.AddComponent("UserRequest", new OpenApiRequestBody + { + Description = "User creation request body", + Content = + { + ["application/json"] = new OpenApiMediaType + { + Schema = new OpenApiSchemaReference("UserSchema", openApiDocument) + } + } + }); + openApiDocument.AddComponent("UserSchema", new OpenApiSchema + { + Type = JsonSchemaType.Object, + Properties = + { + ["name"] = new OpenApiSchema + { + Type = JsonSchemaType.String + }, + ["email"] = new OpenApiSchema + { + Type = JsonSchemaType.String + } + } + }); + + var actual = await openApiDocument.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); + var expected = +""" +{ + "swagger": "2.0", + "info": { }, + "paths": { + "/users": { + "post": { + "consumes": [ + "application/json" + ], + "parameters": [ + { + "$ref": "#/parameters/UserRequest" + } + ], + "responses": { } + } + } + }, + "definitions": { + "UserSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "email": { + "type": "string" + } + } + } + }, + "parameters": { + "UserRequest": { + "in": "body", + "name": "body", + "description": "User creation request body", + "schema": { + "$ref": "#/definitions/UserSchema" + } + } + } +} +"""; + Assert.True(JsonNode.DeepEquals(JsonNode.Parse(expected), JsonNode.Parse(actual))); + } } }