diff --git a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj
index b2e92e560..e3a40ffb7 100644
--- a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj
+++ b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj
@@ -33,7 +33,7 @@
-
+
diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj
index 2231ad6f8..5f0cb79cc 100644
--- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj
+++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj
@@ -23,7 +23,7 @@
true
-
+
diff --git a/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs b/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs
index e01545c61..2f402b8cc 100644
--- a/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs
+++ b/src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs
@@ -63,7 +63,8 @@ protected BaseOpenApiReferenceHolder(string referenceId, OpenApiDocument hostDoc
///
public virtual void SerializeAsV3(IOpenApiWriter writer)
{
- if (!writer.GetSettings().ShouldInlineReference(Reference))
+ if (!writer.GetSettings().ShouldInlineReference(Reference)
+ || Reference.Type == ReferenceType.Tag) // tags are held as references need to drop in.
{
Reference.SerializeAsV3(writer);
}
diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs
index 513355b50..753f2e9d9 100644
--- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs
+++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs
@@ -1,13 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
+using System.Globalization;
using Microsoft.Extensions.Logging;
+using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.Reader;
using Microsoft.OpenApi.Services;
using Microsoft.OpenApi.Tests.UtilityFiles;
+using Microsoft.OpenApi.Writers;
using Moq;
using Xunit;
@@ -235,7 +238,14 @@ public async Task CopiesOverAllReferencedComponentsToTheSubsetDocumentCorrectly(
using var stream = File.OpenRead(filePath);
var settings = new OpenApiReaderSettings();
settings.AddYamlReader();
- var doc = (await OpenApiDocument.LoadAsync(stream, "yaml", settings)).Document;
+ var doc = (await OpenApiDocument.LoadAsync(stream, "yaml", settings)).Document;
+
+ // validated the tags are read as references
+ var openApiOperationTags = doc.Paths["/items"].Operations[OperationType.Get].Tags?.ToArray();
+ Assert.NotNull(openApiOperationTags);
+ Assert.Single(openApiOperationTags);
+ Assert.True(openApiOperationTags[0].UnresolvedReference);
+
var predicate = OpenApiFilterService.CreatePredicate(operationIds: operationIds);
var subsetOpenApiDocument = OpenApiFilterService.CreateFilteredDocument(doc, predicate);
@@ -255,6 +265,26 @@ public async Task CopiesOverAllReferencedComponentsToTheSubsetDocumentCorrectly(
Assert.Single(targetHeaders);
Assert.NotNull(targetExamples);
Assert.Single(targetExamples);
+ // validated the tags of the trimmed document are read as references
+ var trimmedOpenApiOperationTags = subsetOpenApiDocument.Paths["/items"].Operations[OperationType.Get].Tags?.ToArray();
+ Assert.NotNull(trimmedOpenApiOperationTags);
+ Assert.Single(trimmedOpenApiOperationTags);
+ Assert.True(trimmedOpenApiOperationTags[0].UnresolvedReference);
+
+ // Finally try to write the trimmed document as v3 document
+ var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture);
+ var writer = new OpenApiJsonWriter(outputStringWriter)
+ {
+ Settings = new OpenApiWriterSettings()
+ {
+ InlineExternalReferences = true,
+ InlineLocalReferences = true
+ }
+ };
+ subsetOpenApiDocument.SerializeAsV3(writer);
+ await writer.FlushAsync();
+ var result = outputStringWriter.ToString();
+ Assert.NotEmpty(result);
}
[Theory]
diff --git a/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/docWithReusableHeadersAndExamples.yaml b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/docWithReusableHeadersAndExamples.yaml
index 60ee7e5c8..8edeb1945 100644
--- a/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/docWithReusableHeadersAndExamples.yaml
+++ b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/docWithReusableHeadersAndExamples.yaml
@@ -7,6 +7,8 @@ servers:
paths:
/items:
get:
+ tags:
+ - list.items
operationId: getItems
summary: Get a list of items
responses:
diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs
index bed3500d3..d08ad76f9 100644
--- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs
+++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs
@@ -45,6 +45,7 @@ public class OpenApiTagReferenceTest
description: The user was not found.
tags:
- $ref: '#/tags/user'
+ - users.user
components:
schemas:
User:
@@ -60,11 +61,13 @@ public class OpenApiTagReferenceTest
";
readonly OpenApiTagReference _openApiTagReference;
+ readonly OpenApiTagReference _openApiTagReference2;
public OpenApiTagReferenceTest()
{
var result = OpenApiDocument.Parse(OpenApi, "yaml", SettingsFixture.ReaderSettings);
_openApiTagReference = new("user", result.Document);
+ _openApiTagReference2 = new("users.user", result.Document);
}
[Fact]
@@ -73,6 +76,7 @@ public void TagReferenceResolutionWorks()
// Assert
Assert.Equal("user", _openApiTagReference.Name);
Assert.Equal("Operations about users.", _openApiTagReference.Description);
+ Assert.True(_openApiTagReference2.UnresolvedReference);// the target is null
}
[Theory]
@@ -108,5 +112,39 @@ public async Task SerializeTagReferenceAsV31JsonWorks(bool produceTerseOutput)
// Assert
await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput);
}
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public async Task SerializeTagAsV3JsonWorks(bool produceTerseOutput)
+ {
+ // Arrange
+ var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture);
+ var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput });
+
+ // Act
+ _openApiTagReference2.SerializeAsV3(writer);
+ await writer.FlushAsync();
+
+ // Assert
+ Assert.Equal("\"users.user\"", outputStringWriter.ToString());
+ }
+
+ [Theory]
+ [InlineData(true)]
+ [InlineData(false)]
+ public async Task SerializeTagAsV31JsonWorks(bool produceTerseOutput)
+ {
+ // Arrange
+ var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture);
+ var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = produceTerseOutput });
+
+ // Act
+ _openApiTagReference2.SerializeAsV31(writer);
+ await writer.FlushAsync();
+
+ // Assert
+ Assert.Equal("\"users.user\"", outputStringWriter.ToString());
+ }
}
}