Skip to content

Swagger UI sends incorrect format for multipart/form-data arrays #10539

@ahmedtahir2311

Description

@ahmedtahir2311
  • OS: 15.5 (24F74)
  • Browser: chrome
  • Version: latest
  • Method of installation: npm
  • Swagger-UI version: "swagger-jsdoc": "^6.2.8", "swagger-ui-express": "^5.0.1",
  • Swagger/OpenAPI version: [e.g. Swagger 2.0, OpenAPI 3.0]

Content & configuration

Swagger/OpenAPI definition:

/**
 * @swagger
 * /api/ads:
 *   post:
 *     summary: Create a new advertisement
 *     description: Create a new vehicle advertisement with details and images
 *     tags:
 *       - Advertisements
 *     security:
 *       - bearerAuth: []
 *     requestBody:
 *       required: true
 *       content:
 *         multipart/form-data:
 *           schema:
 *             type: object
 *             required:
 *               - country
 *               - state
 *               - city
 *               - ad_status
 *               - category_id
 *               - body_type_id
 *               - chassis_number
 *               - mileage
 *               - maker_id
 *               - model_id
 *               - variant_id
 *               - seating_capacity
 *               - door_count
 *               - cylinder_count
 *               - horse_power
 *               - engine_CC
 *               - transmission
 *               - manufactured_in
 *               - registered_in
 *               - export_status
 *               - fuel_type
 *               - exterior_color
 *               - internal_color
 *               - condition
 *               - contact_through
 *               - sale_category
 *               - price_plan
 *               - images
 *             properties:
 *               country:
 *                 type: string
 *                 description: Country of the vehicle
 *               state:
 *                 type: string
 *                 description: State of the vehicle
 *               city:
 *                 type: string
 *                 description: City of the vehicle
 *               ad_status:
 *                 type: string
 *                 enum: [draft, under_review, published, archived, rejected]
 *                 description: Status of the advertisement
 *               is_deleted:
 *                 type: boolean
 *                 description: Whether the ad is deleted
 *               is_ad_featured:
 *                 type: boolean
 *                 description: Whether the ad is featured
 *               is_driveX_ad:
 *                 type: boolean
 *                 description: Whether the ad is a DriveX ad
 *               category_id:
 *                 type: string
 *                 description: Vehicle category id
 *               body_type_id:
 *                 type: string
 *                 description: Body type of the vehicle id
 *               chassis_number:
 *                 type: string
 *                 description: Chassis number of the vehicle
 *               mileage:
 *                 type: number
 *                 description: Mileage of the vehicle
 *               maker_id:
 *                 type: string
 *                 description: Make/brand of the vehicle id
 *               model_id:
 *                 type: string
 *                 description: Model of the vehicle id
 *               variant_id:
 *                 type: string
 *                 description: Variant of the vehicle model id
 *               year:
 *                 type: number
 *                 description: Year of the vehicle
 *               axle:
 *                 type: string
 *                 description: Axle of the vehicle
 *               seating_capacity:
 *                 type: number
 *                 description: Number of seats in the vehicle
 *               door_count:
 *                 type: number
 *                 description: Number of doors in the vehicle
 *               cylinder_count:
 *                 type: number
 *                 description: Number of cylinders in the engine
 *               horse_power:
 *                 type: number
 *                 description: Engine horsepower
 *               engine_CC:
 *                 type: string
 *                 description: Engine capacity in CC
 *               transmission:
 *                 type: string
 *                 description: Type of transmission
 *                 enum: [manual, automatic]
 *               drive_side:
 *                 type: string
 *                 description: Drive side of the vehicle
 *                 enum: [left, right]
 *               drive_type:
 *                 type: string
 *                 description: Drive type of the vehicle
 *                 enum: [FWD, RWD, 2WD, 4WD]
 *               is_car_insured:
 *                 type: boolean
 *                 description: Whether the car is insured
 *               is_car_warrantied:
 *                 type: boolean
 *                 description: Whether the car is under warranty
 *               remaining_warranty_months:
 *                 type: number
 *                 description: Remaining warranty period in months
 *               manufactured_in:
 *                 type: string
 *                 description: Country of manufacture
 *               registered_in:
 *                 type: number
 *                 description: Year of registration
 *               export_status:
 *                 type: string
 *                 description: Export status of the vehicle
 *               seller_type:
 *                 type: string
 *                 description: Type of seller
 *                 enum: [individual, dealer]
 *               fuel_type:
 *                 type: string
 *                 description: Type of fuel used
 *                 enum: [petrol, diesel, electric, hybrid, cng, lpg]
 *               exterior_color:
 *                 type: string
 *                 description: Hex code of the exterior color
 *               internal_color:
 *                 type: string
 *                 description: Hex code of the interior color
 *               other_details:
 *                 type: string
 *                 description: Additional details about the vehicle
 *               features:
 *                 type: array
 *                 description: List of vehicle features
 *                 items:
 *                   type: string
 *                 style: form
 *                 explode: true
 *               images:
 *                 type: array
 *                 description: List of vehicle images
 *                 items:
 *                   type: string
 *                   format: binary
 *                   description: Image of the vehicle
 *               auction_sheet:
 *                 type: string
 *                 format: binary
 *                 description: Auction sheet file (PDF, max 2MB)
 *               condition:
 *                 type: string
 *                 enum: [new, used, accidental]
 *                 description: Overall condition of the vehicle
 *               condition_score:
 *                 type: array
 *                 description: Detailed condition scores for different aspects
 *                 items:
 *                   type: object
 *                   properties:
 *                     body_symbol_id:
 *                       type: string
 *                       description: ID of the body symbol
 *                     score:
 *                       type: number
 *                       description: Score of the body symbol from 1 to 10
 *               is_contact_preferred:
 *                 type: boolean
 *                 description: Whether the user wants to be contacted through the contact information provided
 *               contact_through:
 *                 type: object
 *                 required:
 *                   - chat
 *                   - sales_assistant
 *                 properties:
 *                   chat:
 *                     type: boolean
 *                     description: Allow contact via chat
 *                   email:
 *                     type: string
 *                     description: Allow contact via email
 *                   phone:
 *                     type: string
 *                     description: Allow contact via phone
 *                   whatsapp:
 *                     type: string
 *                     description: Allow contact via WhatsApp
 *                   line:
 *                     type: string
 *                     description: Allow contact via Line
 *                   sms:
 *                     type: string
 *                     description: Allow contact via SMS
 *                   sales_assistant:
 *                     type: boolean
 *                     description: Allow contact via sales assistant
 *               sale_category:
 *                 type: object
 *                 description: Sale information
 *                 required:
 *                   - negotiable
 *                   - one_price
 *                   - offers
 *                 properties:
 *                   negotiable:
 *                     type: boolean
 *                     description: Whether the vehicle is negotiable
 *                   one_price:
 *                     type: boolean
 *                     description: Whether the vehicle is for one price
 *                   offers:
 *                     type: boolean
 *                     description: Whether the vehicle is for offers
 *               price_plan:
 *                 type: array
 *                 description: Pricing plans for the advertisement
 *                 items:
 *                   type: object
 *                   required:
 *                     - price
 *                     - type
 *                   properties:
 *                     type:
 *                       type: string
 *                       enum: [cash, cash_n_installment, installment]
 *                       description: Type of price plan
 *                     price:
 *                       type: string
 *                       description: Price of the vehicle
 *                     leasing_company:
 *                       type: string
 *                       description: Name of leasing company (for installment plans)
 *                     down_payment:
 *                       type: string
 *                       description: Down payment amount (for installment plans)
 *                     down_payment_percentage:
 *                       type: string
 *                       description: Down payment percentage (for installment plans)
 *                     monthly_installment:
 *                       type: string
 *                     installment_duration:
 *                       type: string
 *                       description: Monthly installment amount (for installment plans)
 *                     total_installment_paid:
 *                       type: string
 *                       description: Total installment paid (for installment plans)
 *                     remaining_installment:
 *                       type: string
 *                       description: Remaining installment (for installment plans)
 *     responses:
 *       200:
 *         description: Advertisement created successfully
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: true
 *                 message:
 *                   type: string
 *                   example: Advertisement created successfully
 *                 data:
 *                   type: object
 *                   description: The created advertisement data
 *       400:
 *         description: Bad request - validation error
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                   example: false
 *                 message:
 *                   type: string
 *                   example: Validation failed
 *                 errors:
 *                   type: object
 *                   description: The validation errors
 *       401:
 *         $ref: '#/components/responses/UnauthorizedError'
 */

Swagger-UI configuration options:

const options: swaggerJSDoc.Options = {
  definition: {
    openapi: "3.0.0",
    info: {
      title: "DriverX API",
      version: "1.0.0",
      description: "API documentation for DriverX application",
    },
    servers: [
      {
        url: process.env.BASE_URL || "http://localhost:8080",
        description:
          process.env.BASE_URL === "http://localhost:8080"
            ? "Development server"
            : "Production server",
      },
    ],
    components: {
      securitySchemes: {
        bearerAuth: {
          type: "http",
          scheme: "bearer",
          bearerFormat: "JWT",
          description: "JWT token for regular user authentication",
        },
        superAdminAuth: {
          type: "http",
          scheme: "bearer",
          bearerFormat: "JWT",
          description:
            "JWT token with super admin privileges (requires admin role)",
        },
      },
      parameters: {
        authHeader: {
          name: "Authorization",
          in: "header",
          description: "JWT token with format: Bearer {token}",
          required: true,
          schema: {
            type: "string",
          },
        },
      },
      responses: {
        UnauthorizedError: {
          description: "Access token is missing or invalid",
          content: {
            "application/json": {
              schema: {
                type: "object",
                properties: {
                  success: {
                    type: "boolean",
                    example: false,
                  },
                  message: {
                    type: "string",
                    example: "Authentication required. No token provided.",
                  },
                },
              },
            },
          },
        },
        ForbiddenError: {
          description: "User does not have required permissions",
          content: {
            "application/json": {
              schema: {
                type: "object",
                properties: {
                  success: {
                    type: "boolean",
                    example: false,
                  },
                  message: {
                    type: "string",
                    example: "You are not authorized to access this resource",
                  },
                },
              },
            },
          },
        },
      },
    },
  },
  apis: ["./src/routes/**/*.ts"],
};

Screenshots

How can we help?

I'm currently using Swagger UI (OpenAPI 3.0) to document and test endpoints that accept multipart/form-data. According to the OpenAPI 3.0 spec, when defining an array with:

type: array
items:
  type: string
style: form
explode: true

...the expected behavior is that Swagger UI will send multiple fields with the same key — e.g.:

features=feature1  
features=feature2  
features=feature3

However, in practice Swagger UI sends a single comma-separated string like:

features=feature1,feature2,feature3

This breaks the contract and causes issues on the backend
I want to reaceive an array of string, in which Multer is gonna help and do some validation with Yup
this is happening for all the fields which are array (even array of string or array of object).

Front will be sending Data like

["one", "two", "three"].forEach(item => {
  formData.append("features", item);
});

I need Guidance on the bases of

  1. how should a Front end send data.
  2. What i can do in swagger configration to get a validated array , which i can then parse and do validation with yup.

If there are any other Solutions available. I am open to them

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions