Skip to content

Parameter examples incorrectly emitted at the Parameter Object level for OpenAPI 3.0 #2669

@mdaneri

Description

@mdaneri

Description

When generating an OpenAPI 3.0 document using Microsoft.OpenApi
3.1.1
, assigning an example via examples for a parameter
component
causes the library to emit examples at the Parameter
Object level
, producing an invalid OpenAPI 3.0 document.

Swagger Editor reports errors such as:

If content is present, the following fields are not allowed:
style, explode, allowReserved, example, examples

According to OpenAPI 3.0.3: - A Parameter Object must contain
either schema (optionally with
example/examples/style/explode/allowReserved) or a
content map. - example / examples must not be added at the
Parameter Object level when content is present. - If examples are used
with content, they must appear under:
parameter.content.<mediaType>.examples.<exampleName>.$ref

Minimal C# reproduction

using Microsoft.OpenApi;
using System.Text.Json.Nodes;

var doc = new OpenApiDocument
{
    Info = new OpenApiInfo
    {
        Title = "Sample API",
        Version = "1.0.0"
    },

    Components = new OpenApiComponents
    {
        Schemas = new Dictionary<string, IOpenApiSchema>()
    }
};

var schema = new OpenApiSchema
{
    Type = JsonSchemaType.Object,
    Properties = new Dictionary<string, IOpenApiSchema>
    {
        ["id"] = new OpenApiSchema { Type = JsonSchemaType.String }
    }
};

var parameter = new OpenApiParameter
{
    Name = "productItems",
    In = ParameterLocation.Header,
    Required = true,
    Description = "Product item in header",
    Content = new Dictionary<string, IOpenApiMediaType>
    {
        ["application/json"] = new OpenApiMediaType
        {
            Schema =  schema
        }
    },
    Examples = new Dictionary<string, IOpenApiExample>
    {
        ["example1"] = new OpenApiExample
        {
            Value =  JsonNode.Parse(@"{ ""id"": ""123"" }")
        }
    }
};

doc.Components.Parameters = new Dictionary<string, IOpenApiParameter>
{
    ["ProductHeader"] = parameter
};


using var writerV2 = new StringWriter();
doc.SerializeAsV2(new OpenApiJsonWriter(writerV2));
string jsonV2 = writerV2.ToString();

File.WriteAllText("openapi_generated-2.0.json", jsonV2);

using var writerV3 = new StringWriter();
doc.SerializeAsV3(new OpenApiJsonWriter(writerV3));
string jsonV3 = writerV3.ToString();

File.WriteAllText("openapi_generated-3.0.json", jsonV3);


using var writerV31 = new StringWriter();
doc.SerializeAsV31(new OpenApiJsonWriter(writerV31));
string jsonV31 = writerV31.ToString();

File.WriteAllText("openapi_generated-3.1.json", jsonV31);


using var writerV32 = new StringWriter();
doc.SerializeAsV32(new OpenApiJsonWriter(writerV32));
string jsonV32 = writerV32.ToString();

File.WriteAllText("openapi_generated-3.2.json", jsonV32);

System.Console.WriteLine("Generated OpenAPI JSON saved to openapi_generated-2.0.json, openapi_generated-3.0.json, openapi_generated-3.1.json, and openapi_generated-3.2.json");

// The generated OpenAPI 3.0 document contains `examples`
// at the Parameter Object level, which is invalid when `content` is present.

// to run:
// dotnet new console -n OpenApiParameterExamplesBugDemo
// cd OpenApiParameterExamplesBugDemo
// dotnet add package Microsoft.OpenApi --version 3.1.1
// dotnet run

Steps to reproduce

  1. Run the code above
  2. Validate the generated document as OpenAPI 3.0 in Swagger Editor
  3. Observe a validation error regarding examples and content

Expected behavior

When emitting OpenAPI 3.0: - Do not write examples at the
Parameter Object level if content is present. - If examples are
provided, they should be placed under:
parameter.content["application/json"].examples["ProductItemExample"].$ref

Actual behavior

The library emits:

"examples": {
  "application/json": {
    "$ref": "#/components/examples/ProductItemExample"
  }
}

The library emits examples at the Parameter Object level, producing an invalid OpenAPI 3.0 document, despite remaining valid for OpenAPI 3.1 and 3.2.

When the document is serialized as Swagger 2.0, the generator also omits the mandatory type field for all non-body parameters (header, query, path, formData).
This results in an invalid Swagger 2.0 definition, as the spec requires a primitive type whenever in is not body.

Affected tooling

  • Swagger Editor
  • API gateways performing strict OpenAPI 3.0 validation
  • Any downstream tooling consuming serialized 3.0 documents

Microsoft.OpenApi version: 3.1.1
Target OpenAPI serialization: 3.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions