diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index bd1ba1cb3..2b7962cdd 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "2.4.2"
+ ".": "2.4.3"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b7d9b73f6..457ff02e5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## [2.4.3](https://github.com/microsoft/OpenAPI.NET/compare/v2.4.2...v2.4.3) (2026-01-16)
+
+
+### Bug Fixes
+
+* Support custom tag ordering ([008576c](https://github.com/microsoft/OpenAPI.NET/commit/008576c31f8dcecf59363c9c2f85d691601faa73))
+* Support custom tag ordering ([7610d07](https://github.com/microsoft/OpenAPI.NET/commit/7610d07bd11a99a4ce1cc31338d180dbd764d952))
+
## [2.4.2](https://github.com/microsoft/OpenAPI.NET/compare/v2.4.1...v2.4.2) (2025-12-22)
diff --git a/Directory.Build.props b/Directory.Build.props
index a64e378aa..7b6a763dc 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -12,7 +12,7 @@
https://github.com/Microsoft/OpenAPI.NET
© Microsoft Corporation. All rights reserved.
OpenAPI .NET
- 2.4.2
+ 2.4.3
diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs
index 031eadb5d..3f12efef1 100644
--- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs
+++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs
@@ -3,6 +3,9 @@
using System;
using System.Collections.Generic;
+#if NET
+using System.Collections.Immutable;
+#endif
using System.IO;
using System.Linq;
using System.Security.Cryptography;
@@ -83,9 +86,15 @@ public ISet? Tags
{
return;
}
- _tags = value is HashSet tags && tags.Comparer is OpenApiTagComparer ?
- tags :
- new HashSet(value, OpenApiTagComparer.Instance);
+ _tags = value switch
+ {
+ HashSet tags when tags.Comparer != EqualityComparer.Default => value,
+ SortedSet => value,
+#if NET
+ ImmutableSortedSet => value,
+#endif
+ _ => new HashSet(value, OpenApiTagComparer.Instance),
+ };
}
}
diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs
index 5e3644f1b..8480269d2 100644
--- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs
+++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs
@@ -3,8 +3,11 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using VerifyXunit;
@@ -2126,6 +2129,79 @@ public void DeduplicatesTags()
Assert.Contains(document.Tags, t => t.Name == "tag2");
}
+ [Fact]
+ public void TagsSupportsCustomComparer()
+ {
+ var document = new OpenApiDocument
+ {
+ Tags = new HashSet(new CaseInsensitiveOpenApiTagEqualityComparer()),
+ };
+
+ Assert.True(document.Tags.Add(new OpenApiTag { Name = "Tag1" }));
+ Assert.False(document.Tags.Add(new OpenApiTag { Name = "tag1" }));
+ Assert.True(document.Tags.Add(new OpenApiTag { Name = "tag2" }));
+ Assert.False(document.Tags.Add(new OpenApiTag { Name = "TAG1" }));
+ Assert.Equal(2, document.Tags.Count);
+ }
+
+ private sealed class CaseInsensitiveOpenApiTagEqualityComparer : IEqualityComparer
+ {
+ public bool Equals(OpenApiTag x, OpenApiTag y)
+ {
+ return string.Equals(x.Name, y.Name, StringComparison.OrdinalIgnoreCase);
+ }
+
+ public int GetHashCode([DisallowNull] OpenApiTag obj)
+ {
+ return obj.Name.GetHashCode(StringComparison.OrdinalIgnoreCase);
+ }
+ }
+
+ [Fact]
+ public void TagsSupportsSortedSets()
+ {
+ var document = new OpenApiDocument
+ {
+ Tags = new SortedSet(new DescendingOpenApiTagComparer())
+ {
+ new OpenApiTag { Name = "tagB" },
+ new OpenApiTag { Name = "tagA" },
+ new OpenApiTag { Name = "tagC" },
+ }
+ };
+
+ var names = document.Tags.Select(t => t.Name);
+ Assert.Equal(["tagC", "tagB", "tagA"], names);
+ Assert.IsType>(document.Tags);
+ }
+
+ private sealed class DescendingOpenApiTagComparer : IComparer
+ {
+ public int Compare(OpenApiTag x, OpenApiTag y)
+ {
+ return string.Compare(y?.Name, x?.Name, StringComparison.Ordinal);
+ }
+ }
+
+ [Fact]
+ public void TagsSupportsImmutableSortedSets()
+ {
+ var document = new OpenApiDocument
+ {
+ Tags = ImmutableSortedSet.Create(
+ new DescendingOpenApiTagComparer(),
+ [
+ new OpenApiTag { Name = "tagB" },
+ new OpenApiTag { Name = "tagA" },
+ new OpenApiTag { Name = "tagC" },
+ ]),
+ };
+
+ var names = document.Tags.Select(t => t.Name);
+ Assert.Equal(["tagC", "tagB", "tagA"], names);
+ Assert.IsType>(document.Tags);
+ }
+
public static TheoryData OpenApiSpecVersions()
{
var values = new TheoryData();