Skip to content

Commit f069dc1

Browse files
authored
Merge pull request #1627 from microsoft/is/do-not-resolve-jsonschema
Removes `JsonSchema` reference resolution when parsing a doc.
2 parents afc40be + 4e07923 commit f069dc1

File tree

13 files changed

+102
-167
lines changed

13 files changed

+102
-167
lines changed

src/Microsoft.OpenApi/Models/OpenApiDocument.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

44
using System;
@@ -446,14 +446,12 @@ private static void WriteHostInfoV2(IOpenApiWriter writer, IList<OpenApiServer>
446446

447447
/// <summary>
448448
/// Walks the OpenApiDocument and sets the host document for all IOpenApiReferenceable objects
449-
/// and resolves JsonSchema references
450449
/// </summary>
451-
public IEnumerable<OpenApiError> ResolveReferences()
450+
public void SetReferenceHostDocument()
452451
{
453-
var resolver = new ReferenceResolver(this);
452+
var resolver = new ReferenceHostDocumentSetter(this);
454453
var walker = new OpenApiWalker(resolver);
455454
walker.Walk(this);
456-
return resolver.Errors;
457455
}
458456

459457
/// <summary>

src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public async Task<ReadResult> ReadAsync(JsonNode jsonNode,
9595
}
9696
}
9797

98-
ResolveReferences(diagnostic, document);
98+
document.SetReferenceHostDocument();
9999
}
100100
catch (OpenApiException ex)
101101
{
@@ -199,16 +199,5 @@ private async Task<OpenApiDiagnostic> LoadExternalRefs(OpenApiDocument document,
199199
var workspaceLoader = new OpenApiWorkspaceLoader(openApiWorkSpace, settings.CustomExternalLoader ?? streamLoader, settings);
200200
return await workspaceLoader.LoadAsync(new OpenApiReference() { ExternalResource = "/" }, document, format ?? OpenApiConstants.Json, null, cancellationToken);
201201
}
202-
203-
private void ResolveReferences(OpenApiDiagnostic diagnostic, OpenApiDocument document)
204-
{
205-
List<OpenApiError> errors = new();
206-
errors.AddRange(document.ResolveReferences());
207-
208-
foreach (var item in errors)
209-
{
210-
diagnostic.Errors.Add(item);
211-
}
212-
}
213202
}
214203
}

src/Microsoft.OpenApi/Services/ReferenceResolver.cs renamed to src/Microsoft.OpenApi/Services/JsonSchemaReferenceResolver.cs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,20 @@
66
using Json.Schema;
77
using Microsoft.OpenApi.Exceptions;
88
using System.Linq;
9-
using Microsoft.OpenApi.Interfaces;
109
using Microsoft.OpenApi.Models;
1110
using Microsoft.OpenApi.Extensions;
1211

1312
namespace Microsoft.OpenApi.Services
1413
{
1514
/// <summary>
16-
/// This class is used to wallk an OpenApiDocument and sets the host document of OpenApiReferences
17-
/// and resolves JsonSchema references.
15+
/// This class is used to walk an OpenApiDocument and resolves JsonSchema references.
1816
/// </summary>
19-
internal class ReferenceResolver : OpenApiVisitorBase
17+
internal class JsonSchemaReferenceResolver : OpenApiVisitorBase
2018
{
2119
private readonly OpenApiDocument _currentDocument;
2220
private readonly List<OpenApiError> _errors = new();
2321

24-
public ReferenceResolver(OpenApiDocument currentDocument)
22+
public JsonSchemaReferenceResolver(OpenApiDocument currentDocument)
2523
{
2624
_currentDocument = currentDocument;
2725
}
@@ -31,18 +29,6 @@ public ReferenceResolver(OpenApiDocument currentDocument)
3129
/// </summary>
3230
public IEnumerable<OpenApiError> Errors => _errors;
3331

34-
/// <summary>
35-
/// Visits the referenceable element in the host document
36-
/// </summary>
37-
/// <param name="referenceable">The referenceable element in the doc.</param>
38-
public override void Visit(IOpenApiReferenceable referenceable)
39-
{
40-
if (referenceable.Reference != null)
41-
{
42-
referenceable.Reference.HostDocument = _currentDocument;
43-
}
44-
}
45-
4632
/// <summary>
4733
/// Resolves schemas in components
4834
/// </summary>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
using Microsoft.OpenApi.Interfaces;
5+
using Microsoft.OpenApi.Models;
6+
7+
namespace Microsoft.OpenApi.Services
8+
{
9+
/// <summary>
10+
/// This class is used to walk an OpenApiDocument and sets the host document of IOpenApiReferenceable objects
11+
/// </summary>
12+
internal class ReferenceHostDocumentSetter : OpenApiVisitorBase
13+
{
14+
private readonly OpenApiDocument _currentDocument;
15+
16+
public ReferenceHostDocumentSetter(OpenApiDocument currentDocument)
17+
{
18+
_currentDocument = currentDocument;
19+
}
20+
21+
/// <summary>
22+
/// Visits the referenceable element in the host document
23+
/// </summary>
24+
/// <param name="referenceable">The referenceable element in the doc.</param>
25+
public override void Visit(IOpenApiReferenceable referenceable)
26+
{
27+
if (referenceable.Reference != null)
28+
{
29+
referenceable.Reference.HostDocument = _currentDocument;
30+
}
31+
}
32+
}
33+
}

test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiDiagnosticTests.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,11 @@ public async Task DiagnosticReportMergedForExternalReference()
5454
ReadResult result;
5555
result = await OpenApiDocument.LoadAsync("OpenApiReaderTests/Samples/OpenApiDiagnosticReportMerged/TodoMain.yaml", settings);
5656

57-
5857
Assert.NotNull(result);
5958
Assert.NotNull(result.OpenApiDocument.Workspace);
6059
result.OpenApiDiagnostic.Errors.Should().BeEquivalentTo(new List<OpenApiError>
6160
{
62-
new OpenApiError("", "[File: ./TodoReference.yaml] Paths is a REQUIRED field at #/"),
63-
new(new OpenApiException("[File: ./TodoReference.yaml] Invalid Reference identifier 'object-not-existing'."))
61+
new OpenApiError("", "[File: ./TodoReference.yaml] Paths is a REQUIRED field at #/")
6462
});
6563
}
6664
}

test/Microsoft.OpenApi.Readers.Tests/OpenApiWorkspaceTests/OpenApiWorkspaceStreamTests.cs

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public async Task LoadingDocumentWithResolveAllReferencesShouldLoadDocumentIntoW
5252
}
5353

5454
[Fact]
55-
public async Task LoadDocumentWithExternalReferenceShouldLoadBothDocumentsIntoWorkspace()
55+
public async Task LoadDocumentWithExternalReferenceShouldLoadExternalDocumentComponentsIntoWorkspace()
5656
{
5757
// Create a reader that will resolve all references
5858
var settings = new OpenApiReaderSettings
@@ -63,28 +63,16 @@ public async Task LoadDocumentWithExternalReferenceShouldLoadBothDocumentsIntoWo
6363
};
6464

6565
ReadResult result;
66-
result = await OpenApiDocument.LoadAsync("V3Tests/Samples/OpenApiWorkspace/TodoMain.yaml", settings);
66+
result = await OpenApiDocument.LoadAsync("V3Tests/Samples/OpenApiWorkspace/TodoMain.yaml", settings);
6767

68-
Assert.NotNull(result.OpenApiDocument.Workspace);
69-
70-
var referencedSchema = result.OpenApiDocument
71-
.Paths["/todos"]
72-
.Operations[OperationType.Get]
73-
.Responses["200"]
74-
.Content["application/json"]
75-
.Schema;
76-
77-
var x = referencedSchema.GetProperties().TryGetValue("subject", out var schema);
78-
Assert.Equal(SchemaValueType.Object, referencedSchema.GetJsonType());
79-
Assert.Equal(SchemaValueType.String, schema.GetJsonType());
80-
81-
var referencedParameter = result.OpenApiDocument
82-
.Paths["/todos"]
83-
.Operations[OperationType.Get]
84-
.Parameters.Select(p => p)
85-
.FirstOrDefault(p => p.Name == "filter");
68+
var externalDocBaseUri = result.OpenApiDocument.Workspace.GetDocumentId("./TodoComponents.yaml");
69+
var schemasPath = "/components/schemas/";
70+
var parametersPath = "/components/parameters/";
8671

87-
Assert.Equal(SchemaValueType.String, referencedParameter.Schema.GetJsonType());
72+
Assert.NotNull(externalDocBaseUri);
73+
Assert.True(result.OpenApiDocument.Workspace.Contains(externalDocBaseUri + schemasPath + "todo"));
74+
Assert.True(result.OpenApiDocument.Workspace.Contains(externalDocBaseUri + schemasPath + "entity"));
75+
Assert.True(result.OpenApiDocument.Workspace.Contains(externalDocBaseUri + parametersPath + "filter"));
8876
}
8977
}
9078

test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation. All rights reserved.
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

44
using System.Collections.Generic;
@@ -100,11 +100,6 @@ public void LoadResponseAndSchemaReference()
100100
{
101101
Schema = new JsonSchemaBuilder()
102102
.Ref("#/definitions/SampleObject2")
103-
.Description("Sample description")
104-
.Required("name")
105-
.Properties(
106-
("name", new JsonSchemaBuilder().Type(SchemaValueType.String)),
107-
("tag", new JsonSchemaBuilder().Type(SchemaValueType.String)))
108103
.Build()
109104
}
110105
}

test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,12 @@
22
// Licensed under the MIT license.
33

44
using System;
5-
using System.Globalization;
65
using System.IO;
76
using System.Linq;
87
using FluentAssertions;
98
using Json.Schema;
109
using Microsoft.OpenApi.Models;
1110
using Microsoft.OpenApi.Reader;
12-
using Microsoft.OpenApi.Writers;
13-
using VerifyXunit;
1411
using Xunit;
1512

1613
namespace Microsoft.OpenApi.Readers.Tests.V2Tests
@@ -30,15 +27,10 @@ public void ShouldParseProducesInAnyOrder()
3027
var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "twoResponses.json"));
3128

3229
var okSchema = new JsonSchemaBuilder()
33-
.Ref("#/definitions/Item")
34-
.Properties(("id", new JsonSchemaBuilder().Type(SchemaValueType.String).Description("Item identifier.")));
30+
.Ref("#/definitions/Item");
3531

3632
var errorSchema = new JsonSchemaBuilder()
37-
.Ref("#/definitions/Error")
38-
.Properties(
39-
("code", new JsonSchemaBuilder().Type(SchemaValueType.Integer).Format("int32")),
40-
("message", new JsonSchemaBuilder().Type(SchemaValueType.String)),
41-
("fields", new JsonSchemaBuilder().Type(SchemaValueType.String)));
33+
.Ref("#/definitions/Error");
4234

4335
var okMediaType = new OpenApiMediaType
4436
{
@@ -147,12 +139,18 @@ public void ShouldParseProducesInAnyOrder()
147139
{
148140
Schemas =
149141
{
150-
["Item"] = okSchema,
151-
["Error"] = errorSchema
142+
["Item"] = new JsonSchemaBuilder()
143+
.Ref("#/definitions/Item")
144+
.Properties(("id", new JsonSchemaBuilder().Type(SchemaValueType.String).Description("Item identifier."))),
145+
["Error"] = new JsonSchemaBuilder()
146+
.Ref("#/definitions/Error")
147+
.Properties(
148+
("code", new JsonSchemaBuilder().Type(SchemaValueType.Integer).Format("int32")),
149+
("message", new JsonSchemaBuilder().Type(SchemaValueType.String)),
150+
("fields", new JsonSchemaBuilder().Type(SchemaValueType.String)))
152151
}
153152
}
154153
}, options => options.Excluding(x => x.Workspace).Excluding(y => y.BaseUri));
155-
156154
}
157155

158156
[Fact]
@@ -169,10 +167,7 @@ public void ShouldAssignSchemaToAllResponses()
169167
.Properties(("id", new JsonSchemaBuilder().Type(SchemaValueType.String).Description("Item identifier."))));
170168

171169
var errorSchema = new JsonSchemaBuilder()
172-
.Ref("#/definitions/Error")
173-
.Properties(("code", new JsonSchemaBuilder().Type(SchemaValueType.Integer).Format("int32")),
174-
("message", new JsonSchemaBuilder().Type(SchemaValueType.String)),
175-
("fields", new JsonSchemaBuilder().Type(SchemaValueType.String)));
170+
.Ref("#/definitions/Error");
176171

177172
var responses = result.OpenApiDocument.Paths["/items"].Operations[OperationType.Get].Responses;
178173
foreach (var response in responses)

test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -44,40 +44,37 @@ public static T Clone<T>(T element) where T : IOpenApiSerializable
4444
public void ParseDocumentWithWebhooksShouldSucceed()
4545
{
4646
// Arrange and Act
47-
var actual = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "documentWithWebhooks.yaml"));
48-
49-
var petSchema = new JsonSchemaBuilder()
50-
.Type(SchemaValueType.Object)
51-
.Required("id", "name")
52-
.Properties(
53-
("id", new JsonSchemaBuilder()
54-
.Type(SchemaValueType.Integer)
55-
.Format("int64")),
56-
("name", new JsonSchemaBuilder()
57-
.Type(SchemaValueType.String)
58-
),
59-
("tag", new JsonSchemaBuilder().Type(SchemaValueType.String))
60-
);
61-
62-
var newPetSchema = new JsonSchemaBuilder()
63-
.Type(SchemaValueType.Object)
64-
.Required("name")
65-
.Properties(
66-
("id", new JsonSchemaBuilder()
67-
.Type(SchemaValueType.Integer)
68-
.Format("int64")),
69-
("name", new JsonSchemaBuilder()
70-
.Type(SchemaValueType.String)
71-
),
72-
("tag", new JsonSchemaBuilder().Type(SchemaValueType.String))
73-
);
47+
var actual = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "documentWithWebhooks.yaml"));
48+
var petSchema = new JsonSchemaBuilder().Ref("#/components/schemas/petSchema");
49+
var newPetSchema = new JsonSchemaBuilder().Ref("#/components/schemas/newPetSchema");
7450

7551
var components = new OpenApiComponents
7652
{
7753
Schemas =
7854
{
79-
["petSchema"] = petSchema,
80-
["newPetSchema"] = newPetSchema
55+
["petSchema"] = new JsonSchemaBuilder()
56+
.Type(SchemaValueType.Object)
57+
.Required("id", "name")
58+
.Properties(
59+
("id", new JsonSchemaBuilder()
60+
.Type(SchemaValueType.Integer)
61+
.Format("int64")),
62+
("name", new JsonSchemaBuilder()
63+
.Type(SchemaValueType.String)
64+
),
65+
("tag", new JsonSchemaBuilder().Type(SchemaValueType.String))
66+
),
67+
["newPetSchema"] = new JsonSchemaBuilder()
68+
.Type(SchemaValueType.Object)
69+
.Required("name")
70+
.Properties(
71+
("id", new JsonSchemaBuilder()
72+
.Type(SchemaValueType.Integer)
73+
.Format("int64")),
74+
("name", new JsonSchemaBuilder()
75+
.Type(SchemaValueType.String)
76+
),
77+
("tag", new JsonSchemaBuilder().Type(SchemaValueType.String)))
8178
}
8279
};
8380

@@ -213,9 +210,11 @@ public void ParseDocumentsWithReusablePathItemInWebhooksSucceeds()
213210
}
214211
};
215212

213+
214+
216215
// Create a clone of the schema to avoid modifying things in components.
217-
var petSchema = components.Schemas["petSchema"];
218-
var newPetSchema = components.Schemas["newPetSchema"];
216+
var petSchema = new JsonSchemaBuilder().Ref("#/components/schemas/petSchema");
217+
var newPetSchema = new JsonSchemaBuilder().Ref("#/components/schemas/newPetSchema");
219218

220219
components.PathItems = new Dictionary<string, OpenApiPathItem>
221220
{

test/Microsoft.OpenApi.Readers.Tests/V3Tests/JsonSchemaTests.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,7 @@ public void ParseBasicSchemaWithReferenceShouldSucceed()
239239
.Ref("#/components/schemas/ExtendedErrorModel")
240240
.AllOf(
241241
new JsonSchemaBuilder()
242-
.Ref("#/components/schemas/ErrorModel")
243-
.Type(SchemaValueType.Object)
244-
.Properties(
245-
("code", new JsonSchemaBuilder().Type(SchemaValueType.Integer).Minimum(100).Maximum(600)),
246-
("message", new JsonSchemaBuilder().Type(SchemaValueType.String)))
247-
.Required("message", "code"),
242+
.Ref("#/components/schemas/ErrorModel"),
248243
new JsonSchemaBuilder()
249244
.Type(SchemaValueType.Object)
250245
.Required("rootCause")

0 commit comments

Comments
 (0)