RicoSuter / NSwag

The Swagger/OpenAPI toolchain for .NET, ASP.NET Core and TypeScript.
http://NSwag.org
MIT License
6.79k stars 1.29k forks source link

Referencing other header parameter suffixes `/schema` #2486

Open daniel-white opened 5 years ago

daniel-white commented 5 years ago

I'm trying to add standard headers to all resources by using $ref.

However when I do something like this:

            var parameters = context.Document.Parameters;

            OpenApiParameter acceptLanguageParameter = parameters.Values.FirstOrDefault(p => p.Kind == OpenApiParameterKind.Header && p.Name.Equals(HeaderNames.AcceptLanguage, StringComparison.OrdinalIgnoreCase));

            if (acceptLanguageParameter == null)
            {
                acceptLanguageParameter = new OpenApiParameter()
                {
                    Name = HeaderNames.AcceptLanguage,
                    Kind = OpenApiParameterKind.Header,
                    Schema = new JsonSchema
                    {
                        Type = JsonObjectType.String,
                        IsNullableRaw = false
                    },
                };

                parameters.Add("AcceptLanguageHeaderParameter", acceptLanguageParameter);
            }

            foreach (OpenApiOperationDescription foo in context.Document.Operations)
            {
                foo.Operation.Parameters.Add(new OpenApiParameter() { Reference = acceptLanguageParameter });
            }

The generated $ref looks like this: #/components/parameters/AcceptLanguageHeaderParameter/schema where the /schema suffix is invalid.

daniel-white commented 5 years ago

Also adding a response reference, causes a null description property. That isn't valid OpenAPI.

"400": {
  "$ref": "#/components/responses/400",
  "description": null
},
Zero3 commented 4 years ago

@daniel-white I'm doing something similar, but without setting Schema explicitly, and I don't see the issue you are seeing.

Perhaps if you move the Type and IsNullableRaw fields one level up, and don't set Schema, it might work for you too.

cjlotz commented 4 years ago

I'm seeing precisely the same behaviour. All parameter references made from context.Documen.Parameters have /schema appended to them when they are added as references to operations. We generate both Swagger2 and OpenApi 3.0 specifications and the weird thing is that the Swagger2 specification generates correctly. See below for output from:

OpenApi 3.0 Spec

image

Same Swagger 2.0 Spec

image

cjlotz commented 4 years ago

@RicoSuter Any additional information that I can provide to assist with troubleshooting this? Any pointers on where to go and hunt for the potential issue?

RicoSuter commented 4 years ago

Probably you also need to manually add the actual OpenApiParameter to the Components.Parameters collection so that it knows where to serialize it to..

zdenek-biberle commented 3 years ago

Just came across this as well. However, instead of generating the schema myself, I was just using an existing schema parsed from a file. Essentially something like this:

(await OpenApiYamlDocument.FromFileAsync("some-file-containing-parameter-references.yaml")).ToYaml()

When given this input:

openapi: 3.0.3
paths:
  /{foo}:
    get:
      operationId: foo
      parameters:
        - $ref: '#/components/parameters/Foo'
      responses:
        '200':
          description: Foo
components:
  parameters:
    Foo:
      in: path
      name: foo
      required: true
      schema:
        type: string

transforms into this:

openapi: 3.0.3
paths:
  /{foo}:
    get:
      operationId: foo
      parameters:
      - $ref: '#/components/parameters/Foo/schema'
      responses:
        200:
          description: Foo
components:
  parameters:
    Foo:
      name: foo
      in: path
      required: true
      schema:
        type: string

which is clearly different & incorrect.

DumDumin commented 1 year ago

I am having the same issue...

The OpenApiDocument.ToJson() Method introduces the "/schema" for references in the parameters.

public string ToJson(SchemaType schemaType, Formatting formatting)
{
    GenerateOperationIds();

    var contractResolver = GetJsonSerializerContractResolver(schemaType);
    return JsonSchemaSerialization.ToJson(this, schemaType, contractResolver, formatting);
}

The Method JsonSchemaSerialization.ToJson() is from the repo https://github.com/RicoSuter/NJsonSchema and works as expected. It uses the contractResolver to serialize. The OpenApiParemeter class contains a Schema Property, which can be resolved by the contractResolver (not completely sure what happens there exactly) and this results in the "/schema" suffix.

The OpenApiDocument.CreateJsonSerializerContractResolver() can be changed to ignore the Schema Property of the OpenApiParameter class:

resolver.IgnoreProperty(typeof(OpenApiParameter), "schema");

With this change you get the desired behaviour discussed above. The same has already be done with the OpenApiResponse class.

Pull Request #4281