-
Notifications
You must be signed in to change notification settings - Fork 281
Description
Describe the bug
After upgrading from the Microsoft.OpenApi nuget package 1.6.28 to 2.0.0, having a nullable schema with a default of 'null' is no longer serialized.
This is somewhat related to #2510, but this particular issue targets guidance, on how to force writing default: null from scratch, instead of reading an existing yaml file.
Behavior in 1.6.28
OpenApiDocument document = new OpenApiDocument
{
Info = new OpenApiInfo
{
Title = "Test",
Version = "1.0.0"
},
Paths = new OpenApiPaths
{
["/"] = new OpenApiPathItem
{
Operations =
{
[OperationType.Get] = new OpenApiOperation
{
Parameters =
{
new OpenApiParameter
{
In = ParameterLocation.Query,
Name = "param1",
Schema = new OpenApiSchema
{
Type = "string",
Nullable = true,
Default = new OpenApiNull()
}
}
},
Responses = { ["204"] = new OpenApiResponse { Description = "No response" } }
}
}
}
}
};
string yaml = document.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0);Generated YAML
openapi: 3.0.4
info:
title: Test
version: 1.0.0
paths:
/:
get:
parameters:
- name: param1
in: query
schema:
type: string
default:
nullable: true
responses:
'204':
description: No responseBehavior in 2.0.0
OpenApiDocument document = new OpenApiDocument
{
Info = new OpenApiInfo
{
Title = "Test",
Version = "1.0.0"
},
Paths = new OpenApiPaths
{
["/"] = new OpenApiPathItem
{
Operations = new Dictionary<HttpMethod, OpenApiOperation>
{
[HttpMethod.Get] = new OpenApiOperation
{
Parameters =
[
new OpenApiParameter
{
In = ParameterLocation.Query,
Name = "param1",
Schema = new OpenApiSchema
{
Type = JsonSchemaType.String | JsonSchemaType.Null,
Default = JsonNode.Parse("\"null\"")
}
}
],
Responses = new OpenApiResponses { ["204"] = new OpenApiResponse { Description = "No response" } }
}
}
}
}
};
string yaml = await document.SerializeAsYamlAsync(OpenApiSpecVersion.OpenApi3_0);Generated YAML
openapi: 3.0.4
info:
title: Test
version: 1.0.0
paths:
/:
get:
parameters:
- name: param1
in: query
schema:
type: string
nullable: true
responses:
'204':
description: No responseActual behavior
The generated YAML in 2.0.0 is missing the default: null.
Expected behavior
The generated YAML in 2.0.0 contains the default: null, as it was in previous versions.
Additional context
The major change from v1 to v2 here is that the OpenApiSchema.Default property no longer accepts an IOpenApiAny, which previously was set using an instance of OpenApiNull, but now expects an instance of JsonNode. The problem with that is, when trying to pass an instance of JsonNode with JsonValueKind.Null, you always end up with null instead of an existing instance. I tried JsonValue.Create<string>(null) and JsonNode.Parse("\"null\"").
Looking at the Microsoft.OpenApi source, the extension method WriteOptionalObject is used, which skips null values:
// default
writer.WriteOptionalObject(OpenApiConstants.Default, Default, (w, d) => w.WriteAny(d));
//...
public static void WriteOptionalObject<T>(
this IOpenApiWriter writer,
string name,
T? value,
Action<IOpenApiWriter, T> action)
{
if (value != null)
{
if (value is IEnumerable values && !values.GetEnumerator().MoveNext())
{
return; // Don't render optional empty collections
}
writer.WriteRequiredObject(name, value, action);
}
}