diff --git a/src/Microsoft.OpenApi/Models/BaseOpenApiReference.cs b/src/Microsoft.OpenApi/Models/BaseOpenApiReference.cs index 28ead3ff7..f47438644 100644 --- a/src/Microsoft.OpenApi/Models/BaseOpenApiReference.cs +++ b/src/Microsoft.OpenApi/Models/BaseOpenApiReference.cs @@ -84,8 +84,14 @@ public string? ReferenceV3 { return Id; } - if (!string.IsNullOrEmpty(Id) && Id is not null && Id.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || - !string.IsNullOrEmpty(Id) && Id is not null && Id.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) + if (!string.IsNullOrEmpty(Id) && Id is not null && + (Id.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || + Id.StartsWith("https://", StringComparison.OrdinalIgnoreCase) || +#if NETSTANDARD2_1 || NETCOREAPP2_1_OR_GREATER || NET5_0_OR_GREATER + Id.Contains("#/components", StringComparison.OrdinalIgnoreCase))) +#else + Id.Contains("#/components"))) +#endif { return Id; } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/ReferenceSamples/STJSchema.json b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/ReferenceSamples/STJSchema.json new file mode 100644 index 000000000..e6c80879d --- /dev/null +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/ReferenceSamples/STJSchema.json @@ -0,0 +1,67 @@ +{ + "type": "object", + "properties": { + "name": { + "type": [ + "string", + "null" + ], + "format": null, + "x-schema-id": null + }, + "parent": { + "type": [ + "object", + "null" + ], + "properties": { + "name": { + "type": [ + "string", + "null" + ], + "format": null, + "x-schema-id": null + }, + "parent": { + "$ref": "#/properties/parent", + "x-schema-id": "Category" + }, + "tags": { + "type": [ + "array", + "null" + ], + "items": { + "type": "object", + "properties": { + "name": { + "type": [ + "string", + "null" + ], + "format": null, + "x-schema-id": null + } + }, + "required": [ + "name" + ], + "x-schema-id": "Tag" + } + } + }, + "required": [ + "name" + ], + "x-schema-id": "Category" + }, + "tags": { + "$ref": "#/properties/parent/properties/tags" + } + }, + "required": [ + "name" + ], + "x-schema-id": "Category" +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/RelativeReferenceTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/RelativeReferenceTests.cs index fd4980b1a..70b0c96a9 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/RelativeReferenceTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/RelativeReferenceTests.cs @@ -312,7 +312,7 @@ public async Task ShouldResolveRelativeSubReferenceUsingParsingContext() parsingContext.StartObject("schemas"); parsingContext.StartObject("Foo"); var document = new OpenApiDocument(); - + // Act var fooComponentSchema = parsingContext.ParseFragment(schemaJsonNode, OpenApiSpecVersion.OpenApi3_1, document); document.AddComponent("Foo", fooComponentSchema); @@ -412,5 +412,28 @@ public async Task ShouldResolveRecursiveRelativeSubReference() Assert.Equal(JsonSchemaType.Array | JsonSchemaType.Null, fooSchemaTagsProperty.Type); Assert.Equal(JsonSchemaType.Object, fooSchemaTagsProperty.Items.Type); } + [Fact] + public async Task ShouldResolveReferencesInSchemasFromSystemTextJson() + { + var filePath = Path.Combine(SampleFolderPath, "STJSchema.json"); + using var fs = File.OpenRead(filePath); + var jsonNode = await JsonNode.ParseAsync(fs); + + var parsingContext = new ParsingContext(new OpenApiDiagnostic()); + var document = new OpenApiDocument(); + var schema = parsingContext.ParseFragment(jsonNode, OpenApiSpecVersion.OpenApi3_1, document); + Assert.NotNull(schema); + + document.AddComponent("Foo", schema); + var tagsProperty = Assert.IsType(schema.Properties["tags"]); + // this is the reference that is generated by STJ schema generator which does not have OAI in context. + Assert.Equal("#/properties/parent/properties/tags", tagsProperty.Reference.ReferenceV3); + // this is the reference that needs to be used in the document for components resolution. + var absoluteReferenceId = $"#/components/schemas/Foo{tagsProperty.Reference.ReferenceV3.Replace("#", string.Empty)}"; + schema.Properties["tags"] = new OpenApiSchemaReference(absoluteReferenceId, document); + var updatedTagsProperty = Assert.IsType(schema.Properties["tags"]); + Assert.Equal(absoluteReferenceId, updatedTagsProperty.Reference.ReferenceV3); + Assert.Equal(JsonSchemaType.Array | JsonSchemaType.Null, updatedTagsProperty.Type); + } } }