Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Represent nullable references within anyOf correctly #247

Merged
merged 2 commits into from
Jul 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -420,10 +420,9 @@ private static OpenApiSchema CreateEnumTypeSchema(this ODataContext context, IEd
Debug.Assert(typeReference != null);

OpenApiSchema schema = new OpenApiSchema();
schema.Nullable = typeReference.IsNullable;
schema.Reference = null;

if (context.Settings.OpenApiSpecVersion >= OpenApiSpecVersion.OpenApi3_0)
if (typeReference.IsNullable && context.Settings.OpenApiSpecVersion >= OpenApiSpecVersion.OpenApi3_0)
{
schema.AnyOf = new List<OpenApiSchema>
{
Expand All @@ -435,6 +434,11 @@ private static OpenApiSchema CreateEnumTypeSchema(this ODataContext context, IEd
Type = ReferenceType.Schema,
Id = typeReference.Definition.FullTypeName()
}
},
new OpenApiSchema
{
Type = "object",
Nullable = true
}
};
}
Expand All @@ -448,6 +452,7 @@ private static OpenApiSchema CreateEnumTypeSchema(this ODataContext context, IEd
Id = typeReference.Definition.FullTypeName()
};
schema.UnresolvedReference = true;
schema.Nullable = typeReference.IsNullable;
}

return schema;
Expand All @@ -459,7 +464,6 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
Debug.Assert(typeReference != null);

OpenApiSchema schema = new OpenApiSchema();
schema.Nullable = typeReference.IsNullable;

// AnyOf will only be valid openApi for version 3
// otherwise the reference should be set directly
Expand All @@ -478,6 +482,11 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
Type = ReferenceType.Schema,
Id = typeReference.Definition.FullTypeName()
}
},
new OpenApiSchema
{
Type = "object",
Nullable = true
}
};
}
Expand All @@ -490,7 +499,8 @@ private static OpenApiSchema CreateStructuredTypeSchema(this ODataContext contex
Type = ReferenceType.Schema,
Id = typeReference.Definition.FullTypeName()
};
schema.UnresolvedReference = true;
schema.UnresolvedReference = true;
schema.Nullable = typeReference.IsNullable;
}

return schema;
Expand All @@ -502,10 +512,9 @@ private static OpenApiSchema CreateTypeDefinitionSchema(this ODataContext contex
Debug.Assert(reference != null);

OpenApiSchema schema = new OpenApiSchema();
schema.Nullable = reference.IsNullable;
schema.Reference = null;

if (context.Settings.OpenApiSpecVersion >= OpenApiSpecVersion.OpenApi3_0)
if (reference.IsNullable && context.Settings.OpenApiSpecVersion >= OpenApiSpecVersion.OpenApi3_0)
{
schema.AnyOf = new List<OpenApiSchema>
{
Expand All @@ -517,6 +526,11 @@ private static OpenApiSchema CreateTypeDefinitionSchema(this ODataContext contex
Type = ReferenceType.Schema,
Id = reference.Definition.FullTypeName()
}
},
new OpenApiSchema
{
Type = "object",
Nullable = true
}
};
}
Expand All @@ -530,6 +544,7 @@ private static OpenApiSchema CreateTypeDefinitionSchema(this ODataContext contex
Id = reference.Definition.FullTypeName()
};
schema.UnresolvedReference = true;
schema.Nullable = reference.IsNullable;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
- Fixes request body and response representation for ref POST and PUT operations #228
- Adds discriminator object to complex types which have derived types #233
- Adds @odata.type property and makes this a required property in schemas that have discriminator objects #243
- Represent nullable references within anyOf correctly #190
</PackageReleaseNotes>
<AssemblyName>Microsoft.OpenApi.OData.Reader</AssemblyName>
<AssemblyOriginatorKeyFile>..\..\tool\Microsoft.OpenApi.OData.snk</AssemblyOriginatorKeyFile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,12 @@ public void CreateEdmTypeSchemaReturnSchemaForNullableCollectionComplexType(Open
""anyOf"": [
{
""$ref"": ""#/components/schemas/Microsoft.OData.Service.Sample.TrippinInMemory.Models.AirportLocation""
},
{
""type"": ""object"",
""nullable"": true
}
],
""nullable"": true
]
}
}".ChangeLineBreaks(), json);
}
Expand Down Expand Up @@ -185,26 +188,40 @@ public void CreateEdmTypeSchemaReturnSchemaForEnumType(bool isNullable, OpenApiS
// & Assert
Assert.NotNull(schema);

// Although the schema will be set
// for openApiV2 nullable will not be serialized
Assert.Equal(isNullable, schema.Nullable);


if (specVersion == OpenApiSpecVersion.OpenApi2_0)
{
Assert.NotNull(schema.Reference);
Assert.Null(schema.AnyOf);
Assert.Equal(ReferenceType.Schema, schema.Reference.Type);
Assert.Equal(enumType.FullTypeName(), schema.Reference.Id);
Assert.Equal(isNullable, schema.Nullable);
}
else
{
Assert.Null(schema.Reference);
Assert.NotNull(schema.AnyOf);
Assert.NotEmpty(schema.AnyOf);
var anyOf = Assert.Single(schema.AnyOf);
Assert.NotNull(anyOf.Reference);
Assert.Equal(ReferenceType.Schema, anyOf.Reference.Type);
Assert.Equal(enumType.FullTypeName(), anyOf.Reference.Id);

if (isNullable)
{
Assert.NotNull(schema.AnyOf);
Assert.NotEmpty(schema.AnyOf);
Assert.Null(schema.Reference);
Assert.Equal(2, schema.AnyOf.Count);
var anyOfRef = schema.AnyOf.FirstOrDefault();
Assert.NotNull(anyOfRef.Reference);
Assert.Equal(ReferenceType.Schema, anyOfRef.Reference.Type);
Assert.Equal(enumType.FullTypeName(), anyOfRef.Reference.Id);
var anyOfNull = schema.AnyOf.Skip(1).FirstOrDefault();
Assert.NotNull(anyOfNull.Type);
Assert.Equal("object", anyOfNull.Type);
Assert.True(anyOfNull.Nullable);
}
else
{
Assert.Null(schema.AnyOf);
Assert.NotNull(schema.Reference);
Assert.Equal(ReferenceType.Schema, schema.Reference.Type);
Assert.Equal(enumType.FullTypeName(), schema.Reference.Id);
}
}
}

Expand Down Expand Up @@ -242,7 +259,8 @@ public void CreateEdmTypeSchemaReturnSchemaForComplexType(bool isNullable, OpenA
Assert.Null(schema.Reference);
Assert.NotNull(schema.AnyOf);
Assert.NotEmpty(schema.AnyOf);
var anyOf = Assert.Single(schema.AnyOf);
Assert.Equal(2, schema.AnyOf.Count);
var anyOf = schema.AnyOf.FirstOrDefault();
Assert.NotNull(anyOf.Reference);
Assert.Equal(ReferenceType.Schema, anyOf.Reference.Type);
Assert.Equal(complex.FullTypeName(), anyOf.Reference.Id);
Expand Down Expand Up @@ -283,10 +301,14 @@ public void CreateEdmTypeSchemaReturnSchemaForEntityType(bool isNullable, OpenAp
Assert.Null(schema.Reference);
Assert.NotNull(schema.AnyOf);
Assert.NotEmpty(schema.AnyOf);
var anyOf = Assert.Single(schema.AnyOf);
Assert.NotNull(anyOf.Reference);
Assert.Equal(ReferenceType.Schema, anyOf.Reference.Type);
Assert.Equal(entity.FullTypeName(), anyOf.Reference.Id);
var anyOfRef = schema.AnyOf.FirstOrDefault();
Assert.NotNull(anyOfRef.Reference);
Assert.Equal(ReferenceType.Schema, anyOfRef.Reference.Type);
Assert.Equal(entity.FullTypeName(), anyOfRef.Reference.Id);
var anyOfNull = schema.AnyOf.Skip(1).FirstOrDefault();
Assert.NotNull(anyOfNull.Type);
Assert.Equal("object", anyOfNull.Type);
Assert.True(anyOfNull.Nullable);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,25 +225,29 @@ public void CreateResponseForEdmFunctionReturnCorrectResponses(bool isFunctionIm
Assert.NotNull(response.Content);
OpenApiMediaType mediaType = response.Content["application/json"];

// For either version, nullable should be set
// and the serializer will ignore for v2
Assert.True(mediaType.Schema.Nullable);

// openApi version 2 should have not use nullable
if (specVersion == OpenApiSpecVersion.OpenApi2_0)
{
Assert.NotNull(mediaType.Schema);
Assert.Null(mediaType.Schema.AnyOf);
Assert.NotNull(mediaType.Schema.Reference);
Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person", mediaType.Schema.Reference.Id);
Assert.True(mediaType.Schema.Nullable);
}
else
{
Assert.NotNull(mediaType.Schema);
Assert.Null(mediaType.Schema.Reference);
Assert.NotNull(mediaType.Schema.AnyOf);
var anyOf = Assert.Single(mediaType.Schema.AnyOf);
Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person", anyOf.Reference.Id);
Assert.Equal(2, mediaType.Schema.AnyOf.Count);
var anyOfRef = mediaType.Schema.AnyOf.FirstOrDefault();
Assert.NotNull(anyOfRef);
Assert.Equal("Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person", anyOfRef.Reference.Id);
var anyOfNull = mediaType.Schema.AnyOf.Skip(1).FirstOrDefault();
Assert.NotNull(anyOfNull.Type);
Assert.Equal("object", anyOfNull.Type);
Assert.True(anyOfNull.Nullable);

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,26 +259,35 @@ public void CreateStructuredTypePropertiesSchemaWithCustomAttributeReturnsCorrec
""anyOf"": [
{
""$ref"": ""#/components/schemas/microsoft.graph.userInsightsSettings""
},
{
""type"": ""object"",
""nullable"": true
}
],
""nullable"": true,
""x-ms-isHidden"": ""true""
},
""regionalAndLanguageSettings"": {
""anyOf"": [
{
""$ref"": ""#/components/schemas/microsoft.graph.regionalAndLanguageSettings""
},
{
""type"": ""object"",
""nullable"": true
}
],
""nullable"": true
]
},
""shiftPreferences"": {
""anyOf"": [
{
""$ref"": ""#/components/schemas/microsoft.graph.shiftPreferences""
},
{
""type"": ""object"",
""nullable"": true
}
],
""nullable"": true
]
}
}
}
Expand Down Expand Up @@ -687,7 +696,7 @@ public void CreatePropertySchemaForNonNullableEnumPropertyReturnSchema(OpenApiSp

IEdmEnumType enumType = model.SchemaElements.OfType<IEdmEnumType>().First(e => e.Name == "Color");
EdmEntityType entitType = new EdmEntityType("NS", "Entity");
IEdmProperty property = new EdmStructuralProperty(entitType, "ColorEnumValue", new EdmEnumTypeReference(enumType, false), "yellow");
IEdmProperty property = new EdmStructuralProperty(entitType, "ColorEnumValue", new EdmEnumTypeReference(enumType, false));

// Act
var schema = context.CreatePropertySchema(property);
Expand All @@ -705,12 +714,7 @@ public void CreatePropertySchemaForNonNullableEnumPropertyReturnSchema(OpenApiSp
else
{
Assert.Equal(@"{
""anyOf"": [
{
""$ref"": ""#/components/schemas/DefaultNs.Color""
}
],
""default"": ""yellow""
""$ref"": ""#/components/schemas/DefaultNs.Color""
}".ChangeLineBreaks(), json);
}
}
Expand Down Expand Up @@ -749,10 +753,13 @@ public void CreatePropertySchemaForNullableEnumPropertyReturnSchema(OpenApiSpecV
""anyOf"": [
{
""$ref"": ""#/components/schemas/DefaultNs.Color""
},
{
""type"": ""object"",
""nullable"": true
}
],
""default"": ""yellow"",
""nullable"": true
""default"": ""yellow""
}".ChangeLineBreaks(), json);
}
}
Expand Down
Loading