Skip to content

Commit bfcfefa

Browse files
Fix OpenApiJsonSchema array parsing (#62051)
1 parent 866d6b8 commit bfcfefa

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

src/OpenApi/src/Schemas/OpenApiJsonSchema.Helpers.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ internal sealed partial class OpenApiJsonSchema
140140
{
141141
type = JsonSchemaType.Array;
142142
var array = new JsonArray();
143+
// Read to process JsonTokenType.StartArray before advancing
144+
reader.Read();
143145
while (reader.TokenType != JsonTokenType.EndArray)
144146
{
145147
array.Add(ReadJsonNode(ref reader));

src/OpenApi/test/Microsoft.AspNetCore.OpenApi.Tests/Services/OpenApiSchemaService/OpenApiSchemaService.ParameterSchemas.cs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,4 +722,93 @@ public static bool TryParse(string value, out Student result)
722722
return true;
723723
}
724724
}
725+
726+
// Regression test for https://github.com/dotnet/aspnetcore/issues/62023
727+
// Testing that the array parsing in our OpenApiJsonSchema works
728+
[Fact]
729+
public async Task CustomConverterThatOutputsArrayWithDefaultValue()
730+
{
731+
// Arrange
732+
var serviceCollection = new ServiceCollection();
733+
serviceCollection.ConfigureHttpJsonOptions(options =>
734+
{
735+
options.SerializerOptions.Converters.Add(new EnumArrayTypeConverter());
736+
});
737+
var builder = CreateBuilder(serviceCollection);
738+
739+
// Act
740+
builder.MapPost("/api", (EnumArrayType e = EnumArrayType.None) => { });
741+
742+
// Assert
743+
await VerifyOpenApiDocument(builder, document =>
744+
{
745+
var operation = document.Paths["/api"].Operations[HttpMethod.Post];
746+
var param = Assert.Single(operation.Parameters);
747+
Assert.NotNull(param.Schema);
748+
Assert.IsType<JsonArray>(param.Schema.Default);
749+
// Type is null, it's up to the user to configure this via a custom schema
750+
// transformer for types with a converter.
751+
Assert.Null(param.Schema.Type);
752+
});
753+
}
754+
755+
[Fact]
756+
public async Task CustomConverterThatOutputsObjectWithDefaultValue()
757+
{
758+
// Arrange
759+
var serviceCollection = new ServiceCollection();
760+
serviceCollection.ConfigureHttpJsonOptions(options =>
761+
{
762+
options.SerializerOptions.Converters.Add(new EnumObjectTypeConverter());
763+
});
764+
var builder = CreateBuilder(serviceCollection);
765+
766+
// Act
767+
builder.MapPost("/api", (EnumArrayType e = EnumArrayType.None) => { });
768+
769+
// Assert
770+
await VerifyOpenApiDocument(builder, document =>
771+
{
772+
var operation = document.Paths["/api"].Operations[HttpMethod.Post];
773+
var param = Assert.Single(operation.Parameters);
774+
Assert.NotNull(param.Schema);
775+
Assert.IsType<JsonObject>(param.Schema.Default);
776+
// Type is null, it's up to the user to configure this via a custom schema
777+
// transformer for types with a converter.
778+
Assert.Null(param.Schema.Type);
779+
});
780+
}
781+
782+
public enum EnumArrayType
783+
{
784+
None = 1
785+
}
786+
787+
public class EnumArrayTypeConverter : JsonConverter<EnumArrayType>
788+
{
789+
public override EnumArrayType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
790+
{
791+
return new EnumArrayType();
792+
}
793+
794+
public override void Write(Utf8JsonWriter writer, EnumArrayType value, JsonSerializerOptions options)
795+
{
796+
writer.WriteStartArray();
797+
writer.WriteEndArray();
798+
}
799+
}
800+
801+
public class EnumObjectTypeConverter : JsonConverter<EnumArrayType>
802+
{
803+
public override EnumArrayType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
804+
{
805+
return new EnumArrayType();
806+
}
807+
808+
public override void Write(Utf8JsonWriter writer, EnumArrayType value, JsonSerializerOptions options)
809+
{
810+
writer.WriteStartObject();
811+
writer.WriteEndObject();
812+
}
813+
}
725814
}

0 commit comments

Comments
 (0)