@hono/zod-openapi outputs examples as an array, causing incompatibility with Swagger UI
Summary
According to the OpenAPI specification, the examples field in a response must be an object. However, when using Schema.openapi({ examples }), if examples is provided as an array, it is output as an array in the generated OpenAPI spec. This causes Swagger UI to fail to parse the examples correctly. Additionally, the examples provided in the schema are not displayed at all in Swagger UI.
Implementation
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
const ResourceOutputSchema = z
.object({
status: z.enum(["pending", "completed"]),
})
.openapi({
description: "The status of the resource",
examples: [{ status: "pending" }, { status: "completed" }],
});
const apiDefinition = createRoute({
method: "get",
path: "/resource/:id",
request: {
params: z.object({
id: z.string(),
}),
},
responses: {
200: {
description: "Successful response",
content: {
"application/json": {
schema: ResourceOutputSchema,
},
},
},
},
});
export const getResourceRoute = (app: OpenAPIHono) => {
return app.openapi(apiDefinition, async (c) => {
return c.json({ status: "completed" as const }, 200);
});
};
Generated OpenAPI Spec
{
"openapi": "3.1.0",
"info": {
"version": "1.0.0",
"title": "Example API"
},
"components": { "schemas": {}, "parameters": {} },
"paths": {
"/resource/:id": {
"get": {
"parameters": [
{
"schema": { "type": "string" },
"required": true,
"name": "id",
"in": "path"
}
],
"responses": {
"200": {
"description": "Successful response",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": ["pending", "completed"]
}
},
"required": ["status"],
"description": "The status of the resource",
"examples": [
{ "status": "pending" },
{ "status": "completed" }
]
}
}
}
}
}
}
}
},
"webhooks": {}
}
The examples provided in the schema are not displayed in Swagger UI:
Additional Notes
If my understanding is incorrect and examples being an array is intended behavior, I’d appreciate clarification. Thank you!
I have same issue
Hi @k3ntar0
This may be zod-to-openapi issue that is used in @hono/zod-openapi. For example, you can use it without @hono/zod-openapi and reproduce this issue:
import { extendZodWithOpenApi, OpenAPIRegistry, OpenApiGeneratorV3 } from '@asteasolutions/zod-to-openapi'
import { z } from 'zod'
extendZodWithOpenApi(z)
const registry = new OpenAPIRegistry()
registry.register(
'Resource',
z
.object({
status: z.enum(['pending', 'completed'])
})
.openapi({
description: 'The status of the resource',
examples: [{ status: 'pending' }, { status: 'completed' }]
})
)
const generator = new OpenApiGeneratorV3(registry.definitions)
const doc = generator.generateDocument({
openapi: '3.0.0',
info: {
version: '1.0.0',
title: 'My API'
}
})
console.log(JSON.stringify(doc, null, 2))
The output (examples will be array):
{
"openapi": "3.0.0",
"info": {
"version": "1.0.0",
"title": "My API"
},
"components": {
"schemas": {
"Resource": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": [
"pending",
"completed"
]
}
},
"required": [
"status"
],
"description": "The status of the resource",
"examples": [
{
"status": "pending"
},
{
"status": "completed"
}
]
}
},
"parameters": {}
},
"paths": {}
}
Can you raise an issue about it on zod-to-openapi repo? They will help us.