Skip to content

Serializer/Deserializer does not work with arrays when type specifier has multiple options #1177

@AndrewRL97

Description

@AndrewRL97

Describe the bug
OpenAPI 3.1 allows types to be specified as an array like so:

{
    "type": ["array", "string", "null"],
    "items": ...
}

When specifying an array like this, and having a corresponding item that would normally be processed by the serializer/deserializer such as a string with a format of "date-time", the serializer is never executed and the field is not converted, causing a type conflict by the validator.

To Reproduce
I'll borrow the steps from issue #699 which is a very closely related serializer issue.

  1. git clone https://github.com/cdimascio/express-openapi-validator.git
    
  2. npm run deps && npm i
    
  3. cd express-openapi-validator/examples/7-response-date-serialization
    
  4. npm start
    
  5. GET http://localhost:3000/v1/date-time
    

This works.

Now modify the app.js /v1/date-time endpoint to the following (array brackets are added):

app.get('/v1/date-time', function (req, res, next) {
  res.json([{
    id: 1,
    created_at: new Date(),
  }]);
});

Update the api.yaml file openapi format to 3.1.0
Also modify the date-time schema of the api.yaml file like so:
Path modified: paths/date-time/get/responses/200/content/application/json/schema

                type: 
                  - array # here you can see even an array of just one type reproduces the issue.
                items:
                  type: object
                  properties:
                    created_at:
                      type: string
                      format: date-time
                    id:
                      type: number  

Rerunning the app and hitting the date-time endpoint then results in the following behavior:

Actual behavior

{
  "message": "/response/0/created_at must be string",
  "errors": [
    {
      "path": "/response/0/created_at",
      "message": "must be string",
      "errorCode": "type.openapi.validation"
    }
  ]
}

Expected behavior

[
  {
    "id": 1,
    "created_at": "2026-04-06T23:07:24.515Z"
  }
]

Additional info

This seems to be related to the array check in the schema.preprocessor file which was updated in #699 :
} else if (schema.type === 'array' && schema.items) {

Here type is only checked as a string constant.

Changing that line to the following:
else if ((schema.type === 'array' || Array.isArray(schema.type) && schema.type.find(elem => elem === 'array')) && schema.items) {

does result in the serializer now executing on the date-string. I did not investigate if this impacted other tests however, or if it is a robust enough solution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions