Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: What is the recommended way to add "encoding - explode: true" to Swagger when using Typebox #733

Open
2 tasks done
bhuynhdev opened this issue Jun 20, 2023 · 3 comments

Comments

@bhuynhdev
Copy link

bhuynhdev commented Jun 20, 2023

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the issue has not already been raised

Issue

I am using Fastify with Typescript through heavy use of Typebox for automatic creation of JSON schema.

For one of my route, I am using "multipart/form-data" as the content type, and I have an array field. In order for Swagger's "Try it out" feature to work with JSON Schema's array validation, I need to specify the "explode: true" option, or else Swagger is just going to send the field as a comma separated string of value, not an actual array (by duplication the field names but with different values in the multipart form data request body)

Typebox allows me to add arbitrary fields to a schema's properties. However, with the new OpenAPI v3 specification, I need the add the "encoding" option in the same depth with the "schema" field, and I don't know how to do it.

Here are examples to illustrate my points:

  1. Without any 'encoding' option
const TestBody = Type.Object({
  color: Type.Array(Type.String()),
});

fastify.post<{ Body: Static<typeof TestBody> }>(
  "/test",
  {
    schema: {
      consumes: ["multipart/form-data"],
      body: TestBody,
    },
  },
  async function (request) {
    console.log(request.body);
    return [];
  }
);

Produce this JSON schema. This has the problem of Swagger UI's "Try it out" trying to send the color field as color=red,blue and not as color=red&color=blue. Only color=red&color=blue will satisfy Fastify AJV; color=red,blue will error out that body/color is not an array

{
  "openapi": "3.0.3",
  "paths": {
    "/test": {
      "post": {
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "color": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "color"
                ]
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    }
  }
}
  1. Tried adding the encoding field through Typebox (FAILED)
const TestBody = Type.Object(
  {
    color: Type.Array(Type.String()),
  },
  { encoding: { color: { style: "form", explode: true } } }
);

fastify.post<{ Body: Static<typeof TestBody> }>(
  "/test",
  {
    schema: {
      consumes: ["multipart/form-data"],
      body: TestBody,
    },
  },
  async function (request) {
    console.log(request.body);
    return [];
  }
);

Produce this JSON schema. However, it doesn't work because "encoding" becomes a subfield of "schema", not its sibling

{
  "openapi": "3.0.3",
  "paths": {
    "/test": {
      "post": {
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "encoding": {
                  "color": {
                    "style": "form",
                    "explode": true
                  }
                },
                "type": "object",
                "properties": {
                  "color": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "required": [
                  "color"
                ]
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    }
  }
}

What option do I have here to implement this feature? I have thought about using the transform option in @fastify/swagger, but transform only affect the scheme, so it is still not a way to add encoding as a sibling of the schema. Are there any options?

@bhuynhdev bhuynhdev changed the title What is the tecommended way to add "encoding - explode: true" to Swagger when using Typebox Question: What is the recommended way to add "encoding - explode: true" to Swagger when using Typebox Jun 20, 2023
@mcollina
Copy link
Member

@sinclairzx81 wdyt?

@bhuynhdev
Copy link
Author

bhuynhdev commented Jun 29, 2023

From some more experimentations and explore, it seems like there is currently zero way to add the encoding object even without Typebox.

Fastify itself only exposes the schema object for modification, and there is no other way to add an extra object as the sibling of the schema field. Since encoding is not standard JSON schema, I kinda understand this situation. Maybe for Swagger/OpenAPI-specific stuff like this, there needs to be some extra option from Fastify-swagger to allow this transformation, like maybe with a decorator, or detecting certain special custom keyword in the schema, and then silently adding an encoding object before finalizing the OpenAPI spec

@mcollina
Copy link
Member

A PR is welcomed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants