diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml
index d7efd6213..b4541f08c 100644
--- a/.github/workflows/sonarcloud.yml
+++ b/.github/workflows/sonarcloud.yml
@@ -29,11 +29,11 @@ jobs:
name: Build
runs-on: windows-latest
steps:
- - name: Set up JDK 11
+ - name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'adopt'
- java-version: 11
+ java-version: 17
- name: Setup .NET 5 # At the moment the scanner requires dotnet 5 https://www.nuget.org/packages/dotnet-sonarscanner
uses: actions/setup-dotnet@v3
with:
diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj
index d595f961b..294219e5f 100644
--- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj
+++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj
@@ -15,7 +15,7 @@
Microsoft.OpenApi.Hidi
hidi
./../../artifacts
- 1.2.6
+ 1.2.7
OpenAPI.NET CLI tool for slicing OpenAPI documents
© Microsoft Corporation. All rights reserved.
OpenAPI .NET
diff --git a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj
index ba2cf568d..2671664c1 100644
--- a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj
+++ b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj
@@ -1,6 +1,7 @@
netstandard2.0
+ latest
true
http://go.microsoft.com/fwlink/?LinkID=288890
https://github.com/Microsoft/OpenAPI.NET
@@ -10,7 +11,7 @@
Microsoft
Microsoft.OpenApi.Readers
Microsoft.OpenApi.Readers
- 1.6.6
+ 1.6.7
OpenAPI.NET Readers for JSON and YAML documents
© Microsoft Corporation. All rights reserved.
OpenAPI .NET
diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiResponseDeserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiResponseDeserializer.cs
index 343dcd2ce..5734ff19d 100644
--- a/src/Microsoft.OpenApi.Readers/V2/OpenApiResponseDeserializer.cs
+++ b/src/Microsoft.OpenApi.Readers/V2/OpenApiResponseDeserializer.cs
@@ -73,35 +73,35 @@ private static void ProcessProduces(MapNode mapNode, OpenApiResponse response, P
}
var produces = context.GetFromTempStorage>(TempStorageKeys.OperationProduces)
- ?? context.GetFromTempStorage>(TempStorageKeys.GlobalProduces);
- if (produces != null)
+ ?? context.GetFromTempStorage>(TempStorageKeys.GlobalProduces)
+ ?? new List { "application/octet-stream" };
+
+ var schema = context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response);
+
+ foreach (var produce in produces)
{
- foreach (var produce in produces)
- {
- var schema = context.GetFromTempStorage(TempStorageKeys.ResponseSchema, response);
- if (response.Content.ContainsKey(produce) && response.Content[produce] != null)
+ if (response.Content.TryGetValue(produce, out var produceValue))
+ {
+ if (schema != null)
{
- if (schema != null)
- {
- response.Content[produce].Schema = schema;
- ProcessAnyFields(mapNode, response.Content[produce], _mediaTypeAnyFields);
- }
+ produceValue.Schema = schema;
+ ProcessAnyFields(mapNode, produceValue, _mediaTypeAnyFields);
}
- else
+ }
+ else
+ {
+ var mediaType = new OpenApiMediaType
{
- var mediaType = new OpenApiMediaType
- {
- Schema = schema
- };
+ Schema = schema
+ };
- response.Content.Add(produce, mediaType);
- }
+ response.Content.Add(produce, mediaType);
}
-
- context.SetTempStorage(TempStorageKeys.ResponseSchema, null, response);
- context.SetTempStorage(TempStorageKeys.ResponseProducesSet, true, response);
}
+
+ context.SetTempStorage(TempStorageKeys.ResponseSchema, null, response);
+ context.SetTempStorage(TempStorageKeys.ResponseProducesSet, true, response);
}
private static void LoadExamples(OpenApiResponse response, ParseNode node)
diff --git a/src/Microsoft.OpenApi.Readers/V2/OpenApiV2Deserializer.cs b/src/Microsoft.OpenApi.Readers/V2/OpenApiV2Deserializer.cs
index 4bb15a8d9..c3f26b896 100644
--- a/src/Microsoft.OpenApi.Readers/V2/OpenApiV2Deserializer.cs
+++ b/src/Microsoft.OpenApi.Readers/V2/OpenApiV2Deserializer.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System.Collections.Generic;
@@ -29,10 +29,11 @@ private static void ParseMap(
return;
}
- foreach (var propertyNode in mapNode)
+ var allFields = fixedFieldMap.Keys.Union(mapNode.Select(static x => x.Name));
+ foreach (var propertyNode in allFields)
{
- propertyNode.ParseField(domainObject, fixedFieldMap, patternFieldMap);
- requiredFields?.Remove(propertyNode.Name);
+ mapNode[propertyNode]?.ParseField(domainObject, fixedFieldMap, patternFieldMap);
+ requiredFields?.Remove(propertyNode);
}
}
@@ -77,16 +78,18 @@ private static void ProcessAnyListFields(
var newProperty = new List();
mapNode.Context.StartObject(anyListFieldName);
-
- var list = anyListFieldMap[anyListFieldName].PropertyGetter(domainObject);
- if (list != null)
+ if (anyListFieldMap.TryGetValue(anyListFieldName, out var fieldName))
{
- foreach (var propertyElement in list)
+ var list = fieldName.PropertyGetter(domainObject);
+ if (list != null)
{
- newProperty.Add(
- OpenApiAnyConverter.GetSpecificOpenApiAny(
- propertyElement,
- anyListFieldMap[anyListFieldName].SchemaGetter(domainObject)));
+ foreach (var propertyElement in list)
+ {
+ newProperty.Add(
+ OpenApiAnyConverter.GetSpecificOpenApiAny(
+ propertyElement,
+ anyListFieldMap[anyListFieldName].SchemaGetter(domainObject)));
+ }
}
}
@@ -104,47 +107,6 @@ private static void ProcessAnyListFields(
}
}
- private static void ProcessAnyMapFields(
- MapNode mapNode,
- T domainObject,
- AnyMapFieldMap anyMapFieldMap)
- {
- foreach (var anyMapFieldName in anyMapFieldMap.Keys.ToList())
- {
- try
- {
- var newProperty = new List();
-
- mapNode.Context.StartObject(anyMapFieldName);
-
- foreach (var propertyMapElement in anyMapFieldMap[anyMapFieldName].PropertyMapGetter(domainObject))
- {
- if (propertyMapElement.Value != null)
- {
- mapNode.Context.StartObject(propertyMapElement.Key);
-
- var any = anyMapFieldMap[anyMapFieldName].PropertyGetter(propertyMapElement.Value);
-
- var newAny = OpenApiAnyConverter.GetSpecificOpenApiAny(
- any,
- anyMapFieldMap[anyMapFieldName].SchemaGetter(domainObject));
-
- anyMapFieldMap[anyMapFieldName].PropertySetter(propertyMapElement.Value, newAny);
- }
- }
- }
- catch (OpenApiException exception)
- {
- exception.Pointer = mapNode.Context.GetLocation();
- mapNode.Context.Diagnostic.Errors.Add(new OpenApiError(exception));
- }
- finally
- {
- mapNode.Context.EndObject();
- }
- }
- }
-
public static IOpenApiAny LoadAny(ParseNode node)
{
return OpenApiAnyConverter.GetSpecificOpenApiAny(node.CreateAny());
diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj
index d727c4627..bc638c883 100644
--- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj
+++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj
@@ -11,7 +11,7 @@
Microsoft
Microsoft.OpenApi
Microsoft.OpenApi
- 1.6.6
+ 1.6.7
.NET models with JSON and YAML writers for OpenAPI specification
© Microsoft Corporation. All rights reserved.
OpenAPI .NET
diff --git a/src/Microsoft.OpenApi/Services/OpenApiReferenceResolver.cs b/src/Microsoft.OpenApi/Services/OpenApiReferenceResolver.cs
index feeceb9af..3b431d4b5 100644
--- a/src/Microsoft.OpenApi/Services/OpenApiReferenceResolver.cs
+++ b/src/Microsoft.OpenApi/Services/OpenApiReferenceResolver.cs
@@ -256,7 +256,7 @@ private void ResolveTags(IList tags)
private T ResolveReference(OpenApiReference reference) where T : class, IOpenApiReferenceable, new()
{
- if (string.IsNullOrEmpty(reference.ExternalResource))
+ if (string.IsNullOrEmpty(reference?.ExternalResource))
{
try
{
diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj
index baeed8767..ebe55934f 100644
--- a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj
+++ b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj
@@ -13,8 +13,8 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
-
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj
index 458e8e627..98ac3a206 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj
+++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj
@@ -1,4 +1,4 @@
-
+
net7.0
false
@@ -51,10 +51,14 @@
Never
+
+ Never
+
Never
+
Never
@@ -268,8 +272,8 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
-
+
+
diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs
index fcf0471ea..0b35d43e8 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs
@@ -163,45 +163,25 @@ public void ShouldParseProducesInAnyOrder()
var reader = new OpenApiStreamReader();
var doc = reader.Read(stream, out var diagnostic);
- var successSchema = new OpenApiSchema()
+ var okSchema = new OpenApiSchema()
{
- Type = "array",
Reference = new OpenApiReference
{
Type = ReferenceType.Schema,
Id = "Item",
HostDocument = doc
},
- Items = new OpenApiSchema()
+ Properties = new Dictionary()
{
- Reference = new OpenApiReference()
- {
- Type = ReferenceType.Schema,
- Id = "Item",
- HostDocument = doc
+ { "id", new OpenApiSchema()
+ {
+ Type = "string",
+ Description = "Item identifier."
+ }
}
}
};
- var okSchema = new OpenApiSchema()
- {
- Reference = new OpenApiReference
- {
- Type = ReferenceType.Schema,
- Id = "Item",
- HostDocument = doc
- },
- Properties = new Dictionary()
- {
- { "id", new OpenApiSchema()
- {
- Type = "string",
- Description = "Item identifier."
- }
- }
- }
- };
-
var errorSchema = new OpenApiSchema()
{
Reference = new OpenApiReference
@@ -211,24 +191,24 @@ public void ShouldParseProducesInAnyOrder()
HostDocument = doc
},
Properties = new Dictionary()
- {
- { "code", new OpenApiSchema()
- {
- Type = "integer",
- Format = "int32"
- }
- },
- { "message", new OpenApiSchema()
- {
- Type = "string"
- }
- },
- { "fields", new OpenApiSchema()
- {
- Type = "string"
- }
- }
- }
+ {
+ { "code", new OpenApiSchema()
+ {
+ Type = "integer",
+ Format = "int32"
+ }
+ },
+ { "message", new OpenApiSchema()
+ {
+ Type = "string"
+ }
+ },
+ { "fields", new OpenApiSchema()
+ {
+ Type = "string"
+ }
+ }
+ }
};
var okMediaType = new OpenApiMediaType
@@ -439,7 +419,7 @@ public void ShouldAllowComponentsThatJustContainAReference()
if (schema2.UnresolvedReference && schema1.Reference.Id == schema2.Reference.Id)
{
// detected a cycle - this code gets triggered
- Assert.True(false, "A cycle should not be detected");
+ Assert.Fail("A cycle should not be detected");
}
}
}
diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs
index 0deb72a5c..3b0f32871 100644
--- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs
+++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs
@@ -182,8 +182,8 @@ public class OpenApiOperationTests
}
}
},
- Extensions = {
- [OpenApiConstants.BodyName] = new OpenApiString("petObject")
+ Extensions = {
+ [OpenApiConstants.BodyName] = new OpenApiString("petObject")
}
},
Responses = new OpenApiResponses
@@ -375,5 +375,62 @@ public void ParseOperationWithResponseExamplesShouldSucceed()
}
);
}
+
+ [Fact]
+ public void ParseOperationWithEmptyProducesArraySetsResponseSchemaIfExists()
+ {
+ // Arrange
+ MapNode node;
+ using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "operationWithEmptyProducesArrayInResponse.json"));
+ node = TestHelper.CreateYamlMapNode(stream);
+
+ // Act
+ var operation = OpenApiV2Deserializer.LoadOperation(node);
+
+ // Assert
+ operation.Should().BeEquivalentTo(
+ new OpenApiOperation()
+ {
+ Responses = new OpenApiResponses()
+ {
+ { "200", new OpenApiResponse()
+ {
+ Description = "OK",
+ Content =
+ {
+ ["application/octet-stream"] = new OpenApiMediaType()
+ {
+ Schema = new OpenApiSchema()
+ {
+ Format = "binary",
+ Description = "The content of the file.",
+ Type = "string",
+ Extensions =
+ {
+ ["x-ms-summary"] = new OpenApiString("File Content")
+ }
+ }
+ }
+ }
+ }}
+ }
+ }
+ );
+ }
+
+ [Fact]
+ public void ParseOperationWithBodyAndEmptyConsumesSetsRequestBodySchemaIfExists()
+ {
+ // Arrange
+ MapNode node;
+ using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "operationWithBodyAndEmptyConsumes.yaml"));
+ node = TestHelper.CreateYamlMapNode(stream);
+
+ // Act
+ var operation = OpenApiV2Deserializer.LoadOperation(node);
+
+ // Assert
+ operation.Should().BeEquivalentTo(_operationWithBody);
+ }
}
}
diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiOperation/operationWithBodyAndEmptyConsumes.yaml b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiOperation/operationWithBodyAndEmptyConsumes.yaml
new file mode 100644
index 000000000..802ec9cf7
--- /dev/null
+++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiOperation/operationWithBodyAndEmptyConsumes.yaml
@@ -0,0 +1,25 @@
+# Modified from https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#operation-object-example
+summary: Updates a pet in the store with request body
+description: ""
+operationId: updatePetWithBody
+consumes: []
+produces:
+- application/json
+- application/xml
+parameters:
+- name: petId
+ in: path
+ description: ID of pet that needs to be updated
+ required: true
+ type: string
+- name: petObject
+ in: body
+ description: Pet to update with
+ required: true
+ schema:
+ type: object
+responses:
+ '200':
+ description: Pet updated.
+ '405':
+ description: Invalid input
diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiOperation/operationWithEmptyProducesArrayInResponse.json b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiOperation/operationWithEmptyProducesArrayInResponse.json
new file mode 100644
index 000000000..d1495fe44
--- /dev/null
+++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiOperation/operationWithEmptyProducesArrayInResponse.json
@@ -0,0 +1,14 @@
+{
+ "produces": [],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "format": "binary",
+ "description": "The content of the file.",
+ "type": "string",
+ "x-ms-summary": "File Content"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Microsoft.OpenApi.SmokeTests/Microsoft.OpenApi.SmokeTests.csproj b/test/Microsoft.OpenApi.SmokeTests/Microsoft.OpenApi.SmokeTests.csproj
index 10ce38c55..c1355fec4 100644
--- a/test/Microsoft.OpenApi.SmokeTests/Microsoft.OpenApi.SmokeTests.csproj
+++ b/test/Microsoft.OpenApi.SmokeTests/Microsoft.OpenApi.SmokeTests.csproj
@@ -16,7 +16,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj
index 02614f5f2..315be5781 100644
--- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj
+++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj
@@ -23,12 +23,12 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
-
-
+
+
+
-
+
all