Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
17 changes: 17 additions & 0 deletions src/OpenApi/src/Extensions/OpenApiSchemaExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ public static IOpenApiSchema CreateOneOfNullableWrapper(this IOpenApiSchema orig
};
}

public static void MakeArrayItemsNullable(this IOpenApiSchema schema)
{
if (schema is not OpenApiSchema { Items: { } items } arraySchema)
{
return;
}

if (items is OpenApiSchema { Type: { } itemType } inlineItemSchema)
{
inlineItemSchema.Type = itemType | JsonSchemaType.Null;
}
else
{
arraySchema.Items = items.CreateOneOfNullableWrapper();
}
}

public static bool IsComponentizedSchema(this OpenApiSchema schema)
=> schema.IsComponentizedSchema(out _);

Expand Down
13 changes: 13 additions & 0 deletions src/OpenApi/src/Extensions/TypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,19 @@ public static bool ShouldApplyNullableRequestSchema(this ApiParameterDescription
return nullabilityInfo.WriteState == NullabilityState.Nullable;
}

public static bool ShouldApplyNullableArrayElementSchema(this ApiParameterDescription apiParameterDescription)
{
if (apiParameterDescription.Type is not { IsArray: true } ||
apiParameterDescription.ParameterDescriptor is not IParameterInfoParameterDescriptor { ParameterInfo: { } parameterInfo })
{
return false;
}

var nullabilityInfoContext = new NullabilityInfoContext();
var nullabilityInfo = nullabilityInfoContext.Create(parameterInfo);
return nullabilityInfo.ElementType?.WriteState == NullabilityState.Nullable;
}

public static bool ShouldApplyNullablePropertySchema(this JsonPropertyInfo jsonPropertyInfo)
{
if (jsonPropertyInfo.AttributeProvider is not PropertyInfo propertyInfo)
Expand Down
15 changes: 14 additions & 1 deletion src/OpenApi/src/Services/OpenApiDocumentService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,19 @@ private static bool IsServerSentEventsContentType(string contentType)
continue;
}

var parameterSchema = await _componentService.GetOrCreateSchemaAsync(
Comment thread
Youssef1313 marked this conversation as resolved.
document,
GetTargetType(description, parameter),
scopedServiceProvider,
schemaTransformers,
parameter,
cancellationToken: cancellationToken);

if (parameter.ShouldApplyNullableArrayElementSchema())
{
parameterSchema.MakeArrayItemsNullable();
}

var openApiParameter = new OpenApiParameter
{
Name = parameter.Name,
Expand All @@ -599,7 +612,7 @@ private static bool IsServerSentEventsContentType(string contentType)
_ => ParameterLocation.Query
},
Required = IsRequired(parameter),
Schema = await _componentService.GetOrCreateSchemaAsync(document, GetTargetType(description, parameter), scopedServiceProvider, schemaTransformers, parameter, cancellationToken: cancellationToken),
Schema = parameterSchema,
Description = GetParameterDescriptionFromAttribute(parameter)
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -459,10 +459,7 @@ await VerifyOpenApiDocument(builder, document =>
[(Guid[] id) => { }, JsonSchemaType.String, false],
[(Guid?[] id) => { }, JsonSchemaType.String, true],
[(string[] id) => { }, JsonSchemaType.String, false],
// Due to runtime restrictions, we can't resolve nullability
// info for reference types as element types so this will still
// encode as non-nullable.
[(string?[] id) => { }, JsonSchemaType.String, false],
[(string?[] id) => { }, JsonSchemaType.String, true],
[(DateTime[] id) => { }, JsonSchemaType.String, false],
[(DateTime?[] id) => { }, JsonSchemaType.String, true],
[(DateTimeOffset[] id) => { }, JsonSchemaType.String, false],
Expand Down
Loading