Skip to content

Commit c8607a4

Browse files
authored
feat(zod): support zod meta title in generated JSON schema (#774)
## Summary - Add support for `title` field in zod4 converter's global registry handling - Enhance test coverage for title field functionality including union examples **Explanation why it's useful:** When using unions in array, it's helpful for openapi UIs to display the title of possible objects in array before: <img width="342" height="214" alt="Screenshot 2025-07-15 at 16 02 57" src="https://github.com/user-attachments/assets/bfa1a9d1-faac-47c0-9cda-14df250caeb5" /> after: <img width="394" height="216" alt="Screenshot 2025-07-15 at 16 05 27" src="https://github.com/user-attachments/assets/0f822823-f99b-495b-ba63-0bbd482778f6" /> I plan to submit one more PR with better handling for discriminated unions, but it should be good enough for start
1 parent e1b0a55 commit c8607a4

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

packages/zod/src/zod4/converter.meta.test.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
} from './registries'
88

99
const customSchema1 = z.string().meta({
10+
title: 'Custom String Schema',
1011
description: 'description',
1112
examples: ['a', 'b'],
1213
})
@@ -45,11 +46,20 @@ JSON_SCHEMA_OUTPUT_REGISTRY.add(customSchema3, {
4546
examples: ['1'],
4647
})
4748

49+
const customSchemaWithTitleOnly = z.string().meta({
50+
title: 'Title Only Schema',
51+
})
52+
53+
const unionSchema = z.union([
54+
z.string().meta({ title: 'String Option' }),
55+
z.number().meta({ title: 'Number Option' }),
56+
])
57+
4858
testSchemaConverter([
4959
{
5060
name: 'customSchema1',
5161
schema: customSchema1,
52-
input: [true, { type: 'string', description: 'description', examples: ['a', 'b'] }],
62+
input: [true, { type: 'string', title: 'Custom String Schema', description: 'description', examples: ['a', 'b'] }],
5363
},
5464
{
5565
name: 'customSchema1_unsupported_examples',
@@ -93,4 +103,19 @@ testSchemaConverter([
93103
schema: z.string().readonly(),
94104
input: [true, { type: 'string', readOnly: true }],
95105
},
106+
{
107+
name: 'customSchemaWithTitleOnly',
108+
schema: customSchemaWithTitleOnly,
109+
input: [true, { type: 'string', title: 'Title Only Schema' }],
110+
},
111+
{
112+
name: 'unionSchema',
113+
schema: unionSchema,
114+
input: [true, {
115+
anyOf: [
116+
{ type: 'string', title: 'String Option' },
117+
{ type: 'number', title: 'Number Option' },
118+
],
119+
}],
120+
},
96121
])

packages/zod/src/zod4/converter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@ export class ZodToJsonSchemaConverter implements ConditionalSchemaConverter {
581581

582582
if (global) {
583583
return {
584+
title: global.title,
584585
description: global.description,
585586
examples: Array.isArray(global.examples) ? global.examples : undefined,
586587
}

0 commit comments

Comments
 (0)