Skip to content
This repository was archived by the owner on Nov 11, 2025. It is now read-only.

Commit 82a4229

Browse files
Copilotbaywet
andcommitted
Add deserialization support for $self in V31 and V32 deserializers and move tests to OpenApiDocumentTests
Co-authored-by: baywet <7905502+baywet@users.noreply.github.com>
1 parent 518abac commit 82a4229

4 files changed

Lines changed: 100 additions & 240 deletions

File tree

src/Microsoft.OpenApi/Reader/V31/OpenApiDocumentDeserializer.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,21 @@ internal static partial class OpenApiV31Deserializer
3030
private static readonly PatternFieldMap<OpenApiDocument> _openApiPatternFields = new()
3131
{
3232
// We have no semantics to verify X- nodes, therefore treat them as just values.
33-
{s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) => o.AddExtension(p, LoadExtension(p, n))}
33+
{s => s.StartsWith(OpenApiConstants.ExtensionFieldNamePrefix, StringComparison.OrdinalIgnoreCase), (o, p, n, _) =>
34+
{
35+
if (p.Equals("x-oai-$self", StringComparison.OrdinalIgnoreCase))
36+
{
37+
var value = n.GetScalarValue();
38+
if (value != null && Uri.TryCreate(value, UriKind.Absolute, out var self))
39+
{
40+
o.Self = self;
41+
}
42+
}
43+
else
44+
{
45+
o.AddExtension(p, LoadExtension(p, n));
46+
}
47+
}}
3448
};
3549

3650
public static OpenApiDocument LoadOpenApi(RootNode rootNode, Uri location)

src/Microsoft.OpenApi/Reader/V32/OpenApiDocumentDeserializer.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ internal static partial class OpenApiV32Deserializer
1818
},
1919
{"info", (o, n, _) => o.Info = LoadInfo(n, o)},
2020
{"jsonSchemaDialect", (o, n, _) => { if (n.GetScalarValue() is string {} sjsd && Uri.TryCreate(sjsd, UriKind.Absolute, out var jsd)) {o.JsonSchemaDialect = jsd;}} },
21+
{"$self", (o, n, _) => { if (n.GetScalarValue() is string {} sself && Uri.TryCreate(sself, UriKind.Absolute, out var self)) {o.Self = self;}} },
2122
{"servers", (o, n, _) => o.Servers = n.CreateList(LoadServer, o)},
2223
{"paths", (o, n, _) => o.Paths = LoadPaths(n, o)},
2324
{"webhooks", (o, n, _) => o.Webhooks = n.CreateMap(LoadPathItem, o)},

test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentSelfPropertyTests.cs

Lines changed: 0 additions & 239 deletions
This file was deleted.

test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2282,5 +2282,89 @@ public async Task SerializeDocWithEmptyOperationSecurityWorks()
22822282
Assert.NotNull(actualOperation.Security);
22832283
Assert.Empty(actualOperation.Security);
22842284
}
2285+
2286+
[Fact]
2287+
public async Task SerializeDocumentWithSelfPropertyAsV32Works()
2288+
{
2289+
// Arrange
2290+
var doc = new OpenApiDocument
2291+
{
2292+
Info = new OpenApiInfo
2293+
{
2294+
Title = "Self Property Test",
2295+
Version = "1.0.0"
2296+
},
2297+
Self = new Uri("https://example.org/api/openapi.json")
2298+
};
2299+
2300+
var expected = @"openapi: '3.2.0'
2301+
$self: https://example.org/api/openapi.json
2302+
info:
2303+
title: Self Property Test
2304+
version: 1.0.0
2305+
paths: { }";
2306+
2307+
// Act
2308+
var actual = await doc.SerializeAsYamlAsync(OpenApiSpecVersion.OpenApi3_2);
2309+
2310+
// Assert
2311+
Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), actual.MakeLineBreaksEnvironmentNeutral());
2312+
}
2313+
2314+
[Fact]
2315+
public async Task SerializeDocumentWithSelfPropertyAsV31WritesAsExtension()
2316+
{
2317+
// Arrange
2318+
var doc = new OpenApiDocument
2319+
{
2320+
Info = new OpenApiInfo
2321+
{
2322+
Title = "Self Property Test",
2323+
Version = "1.0.0"
2324+
},
2325+
Self = new Uri("https://example.org/api/openapi.json")
2326+
};
2327+
2328+
var expected = @"openapi: '3.1.2'
2329+
info:
2330+
title: Self Property Test
2331+
version: 1.0.0
2332+
paths: { }
2333+
x-oai-$self: https://example.org/api/openapi.json";
2334+
2335+
// Act
2336+
var actual = await doc.SerializeAsYamlAsync(OpenApiSpecVersion.OpenApi3_1);
2337+
2338+
// Assert
2339+
Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), actual.MakeLineBreaksEnvironmentNeutral());
2340+
}
2341+
2342+
[Fact]
2343+
public async Task SerializeDocumentWithSelfPropertyAsV30WritesAsExtension()
2344+
{
2345+
// Arrange
2346+
var doc = new OpenApiDocument
2347+
{
2348+
Info = new OpenApiInfo
2349+
{
2350+
Title = "Self Property Test",
2351+
Version = "1.0.0"
2352+
},
2353+
Self = new Uri("https://example.org/api/openapi.json")
2354+
};
2355+
2356+
var expected = @"openapi: 3.0.4
2357+
info:
2358+
title: Self Property Test
2359+
version: 1.0.0
2360+
paths: { }
2361+
x-oai-$self: https://example.org/api/openapi.json";
2362+
2363+
// Act
2364+
var actual = await doc.SerializeAsYamlAsync(OpenApiSpecVersion.OpenApi3_0);
2365+
2366+
// Assert
2367+
Assert.Equal(expected.MakeLineBreaksEnvironmentNeutral(), actual.MakeLineBreaksEnvironmentNeutral());
2368+
}
22852369
}
22862370
}

0 commit comments

Comments
 (0)