question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Incorrect nullable annotation for array of nullable items

See original GitHub issue

I have a need in my project to fine-tune the validation of collection items. And I would like to reflect information about these constraints in the generated OpenAPI schema. However, I ran into one problem that doesn’t seem to have a workaround.

Since the built-in validation attributes do not support validation of collection items, I use custom validation attributes and custom schema filters (which use these attributes) to enrich the generated schema with appropriate metadata. Filters check if a member has a matching attribute and override the corresponding schema metadata using that attribute. Below are examples of a model and one such filter that should override the nullable annotation (examples are simplified for brevity).

public class TestModel
{
    [NonNullableItems]
    public List<int?> Data1 { get; set; }
    public List<int?> Data2 { get; set; }
}
public class NonNullableItemsSchemaFilter : ISchemaFilter
{
    public void Apply(OpenApiSchema schema, SchemaFilterContext context)
    {
        var attribute = context.MemberInfo
            ?.GetCustomAttributes<NonNullableItemsAttribute>()
            .FirstOrDefault();

        if (attribute != null)
        {
            schema.Items.Nullable = false;
        }
    }
}

I expect that for the described model using the described filter, the OpenAPI schema shown below will be generated.

"TestModel": {
  "type": "object",
  "properties": {
    "data1": {
      "type": "array",
      "nullable": true,
      "items": {
        "type": "string",
        "nullable": false
      }
    },
    "data2": {
      "type": "array",
      "nullable": true,
      "items": {
        "type": "string",
        "nullable": true
      }
    },
  },
  "additionalProperties": false
}

In fact, a schema is generated that does not contain nullable annotations for array items, i.e. the default value is assumed (false, according to the OpenAPI specification). This scheme incorrectly describes the behavior of the API, since its implementation allows null values as items of the data1 array.

I checked the source code of the library and found out that this occurs because nullable annotation is explicitly populated only for object property schemas. In all other cases, including schemas for array items, the default value is retained.

I could get around this limitation by explicitly populating nullable in my filter depending on the attribute presence (and not just overwriting it if the attribute is present). However, this requires determining whether the corresponding member is nullable, which implies analysis of the underlying data type, a nullable context, a serializer behavior. This problem is difficult to solve within a schema filter due to lack of data. Moreover, it is impractical to solve it within a schema filter, since this will lead to duplication of a logic already implemented within the library.

The described behavior is actual for version 6.1.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:1
  • Comments:12 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
Eneumancommented, Mar 23, 2022

@kristinn-is Yes I did and the problem is that List is treated like a Object and the nullabillity information for the contained type is not used.

There are several ways to fix this so I need to discuss this with @domaindrivendev before making the PR.

I browsed the Open API specification and I couldn’t find that it was allowed to set the nullable attribute on the items type attribute, so I think that the result from this would be something like this:

"TestModel": {
  "type": "object",
  "properties": {
    "data1": {
      "type": "array",
      "nullable": true,
      "items": {
        $ref: '#/components/schemas/Pet'
      }
    },
  },
  "additionalProperties": false
}

And then the nullability is set on the ref object. Ref would only be used if the List<> contains a nullable reference type, otherwise it would look the same as today.

@domaindrivendev I’m thinking about modifying public DataContract GetDataContractForType(Type type) and introduce a new check for “GenericList” as a new DataType. Then adding a new DataContract.ForGenericList, and finally modifying private OpenApiSchema GenerateConcreteSchema(DataContract dataContract, SchemaRepository schemaRepository) to hande the new DataType and to set returnAsReference = true if the List<> has a nullable type. Let me know if you want me to proceed.

1reaction
Eneumancommented, Mar 5, 2022

PR fixing problems with nullable reference types in dictionary just got merged so I’ll take a look at this next week 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Annotate an Array NonNull? - java
How can I say that an array consists of non-null elements? I've tested: public static void test(@NonNull String[] a) ...
Read more >
Nullability of Java arrays is read incorrectly if ...
Nullability of Java arrays is read incorrectly if @Nullable annotation has both targets TYPE_USE and VALUE_PARAMETER.
Read more >
NullablePrimitiveArray
The problem. For @Nullable type annotations (such as org.checkerframework.checker.nullness.qual.Nullable ), @Nullable byte[] means a 'non-null array of ...
Read more >
Incorrect @Nullable JSR305 annotations generated when ...
Currently, the rule NotRequiredRule generates incorrect @Nullable annotations for fields that get correctly generated with @Nonnull.
Read more >
Nullable reference types
Nullable contexts enable fine-grained control for how the compiler interprets reference type variables. The nullable annotation context ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found