diff --git a/src/Microsoft.OpenApi/Models/OpenApiReference.cs b/src/Microsoft.OpenApi/Models/OpenApiReference.cs index fd2317803..1fc206bd3 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiReference.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiReference.cs @@ -95,6 +95,10 @@ public string ReferenceV3 { return Id; } + if (Id.StartsWith("http")) + { + return Id; + } return "#/components/" + Type.GetDisplayName() + "/" + Id; } @@ -236,6 +240,11 @@ private string GetExternalReferenceV3() return ExternalResource + "#" + Id; } + if (Id.StartsWith("http")) + { + return Id; + } + return ExternalResource + "#/components/" + Type.GetDisplayName() + "/" + Id; } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs index 4ee1c3fbd..66fb0fa1e 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs @@ -1,12 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; using System; using System.Collections.Generic; -using System.Runtime; using System.Text.Json.Nodes; namespace Microsoft.OpenApi.Models.References diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs index a56590bf1..d6c9d0fcf 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiV31Deserializer.cs @@ -157,9 +157,11 @@ private static (string, string) GetReferenceIdAndExternalResource(string pointer string refId = !pointer.Contains('#') ? pointer : refSegments.Last(); var isExternalResource = !refSegments.First().StartsWith("#"); - string externalResource = isExternalResource - ? $"{refSegments.First()}/{refSegments[1].TrimEnd('#')}" - : null; + string externalResource = null; + if (isExternalResource && pointer.Contains('#')) + { + externalResource = $"{refSegments.First()}/{refSegments[1].TrimEnd('#')}"; + } return (refId, externalResource); } diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 81991fd63..e1f54a276 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -42,14 +42,14 @@ OpenApiCallbackReferenceTests.cs + + PreserveNewest + + PreserveNewest - - - - \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs index c6927fcfb..56dc228e0 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs @@ -1642,5 +1642,54 @@ public void SerializeV31DocumentWithRefsInWebhooksWorks() var actual = stringWriter.ToString(); actual.MakeLineBreaksEnvironmentNeutral().Should().BeEquivalentTo(expected.MakeLineBreaksEnvironmentNeutral()); } + + [Fact] + public void SerializeDocWithDollarIdInDollarRefSucceeds() + { + var expected = @"openapi: '3.1.0' +info: + title: Simple API + version: 1.0.0 +paths: + /box: + get: + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: https://foo.bar/Box + /circle: + get: + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: https://foo.bar/Circle +components: + schemas: + Box: + $id: https://foo.bar/Box + type: object + properties: + width: + type: number + height: + type: number + Circle: + $id: https://foo.bar/Circle + type: object + properties: + radius: + type: number +"; + var doc = OpenApiDocument.Load("Models/Samples/docWithDollarId.yaml").OpenApiDocument; + + var actual = doc.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_1); + actual.MakeLineBreaksEnvironmentNeutral().Should().BeEquivalentTo(expected.MakeLineBreaksEnvironmentNeutral()); + } } } diff --git a/test/Microsoft.OpenApi.Tests/Models/Samples/docWithDollarId.yaml b/test/Microsoft.OpenApi.Tests/Models/Samples/docWithDollarId.yaml new file mode 100644 index 000000000..e8916f895 --- /dev/null +++ b/test/Microsoft.OpenApi.Tests/Models/Samples/docWithDollarId.yaml @@ -0,0 +1,39 @@ +openapi: 3.1.0 +info: + title: Simple API + version: 1.0.0 +paths: + /box: + get: + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: https://foo.bar/Box + /circle: + get: + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: https://foo.bar/Circle +components: + schemas: + Box: + $id: https://foo.bar/Box + type: object + properties: + width: + type: number + height: + type: number + Circle: + $id: https://foo.bar/Circle + type: object + properties: + radius: + type: number