From 8a2b07c81d82a7c2dd0d5eb3e5589b103fbc299c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 21 Jan 2025 15:31:44 -0500 Subject: [PATCH 1/3] chore: linting Signed-off-by: Vincent Biret --- .../Models/References/OpenApiRequestBodyReference.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs index 598d70310..5b8001990 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 { From b84ea194a16e03a1f2b6f56af892eb6288d5627a Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 22 Jan 2025 10:24:08 -0500 Subject: [PATCH 2/3] fix: request body references are converted to v2 properly Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi/Models/OpenApiDocument.cs | 2 +- src/Microsoft.OpenApi/Models/OpenApiOperation.cs | 4 ++-- src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs | 2 +- .../References/OpenApiRequestBodyReference.cs | 13 +++++++++++++ 4 files changed, 17 insertions(+), 4 deletions(-) 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 5b8001990..59fb27724 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs @@ -119,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); + } + } } } From 03436cb8560227fd8b2e07b3405e6d077df663b3 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 22 Jan 2025 15:11:53 -0500 Subject: [PATCH 3/3] chore: adds unit test for v2 request body reference fix Signed-off-by: Vincent Biret --- .../V2Tests/OpenApiOperationTests.cs | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) 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))); + } } }