diff --git a/packages/zod/src/zod4/converter.processed.test.ts b/packages/zod/src/zod4/converter.processed.test.ts index 8feee8522..fc6d8032e 100644 --- a/packages/zod/src/zod4/converter.processed.test.ts +++ b/packages/zod/src/zod4/converter.processed.test.ts @@ -18,4 +18,10 @@ testSchemaConverter([ input: [true, { type: 'string' }], output: [false, {}], }, + { + name: 'preprocess(x => x, z.string())', + schema: z.preprocess(x => x, z.string()), + input: [true, { type: 'string' }], + output: [true, { type: 'string' }], + }, ]) diff --git a/packages/zod/src/zod4/converter.ts b/packages/zod/src/zod4/converter.ts index d25852a7f..9347b6242 100644 --- a/packages/zod/src/zod4/converter.ts +++ b/packages/zod/src/zod4/converter.ts @@ -519,7 +519,15 @@ export class ZodToJsonSchemaConverter implements ConditionalSchemaConverter { case 'pipe': { const pipe = schema as $ZodPipe - return this.#convert(options.strategy === 'input' ? pipe._zod.def.in : pipe._zod.def.out, options, lazyDepth, structureDepth) + return this.#convert( + // prefer out schema when in schema is preprocess/transform + options.strategy === 'input' && pipe._zod.def.in._zod.def.type !== 'transform' + ? pipe._zod.def.in + : pipe._zod.def.out, + options, + lazyDepth, + structureDepth, + ) } case 'readonly': {