@@ -3,6 +3,8 @@ import * as checks from "./checks.js";
33import * as core from "./core.js" ;
44import { Doc } from "./doc.js" ;
55import type * as errors from "./errors.js" ;
6+ import type * as JSONSchema from "./json-schema.js" ;
7+ import { createJSONSchema , stringFormatMap , type JSONSchemaContext } from "./json-schema-lite.js" ;
68import { parse , parseAsync , safeParse , safeParseAsync } from "./parse.js" ;
79import * as regexes from "./regexes.js" ;
810import type { StandardSchemaV1 } from "./standard-schema.js" ;
@@ -149,6 +151,9 @@ export interface _$ZodTypeInternals {
149151 /** An optional method used to override `toJSONSchema` logic. */
150152 toJSONSchema ?: ( ) => unknown ;
151153
154+ /** Minimal JSON Schema representation for this schema. */
155+ getJSONSchema : ( ctx ?: JSONSchemaContext ) => JSONSchema . BaseSchema ;
156+
152157 /** @internal The parent of this schema. Only set during certain clone operations. */
153158 parent ?: $ZodType | undefined ;
154159}
@@ -181,6 +186,9 @@ export const $ZodType: core.$constructor<$ZodType> = /*@__PURE__*/ core.$constru
181186 inst . _zod . def = def ; // set _def property
182187 inst . _zod . bag = inst . _zod . bag || { } ; // initialize _bag object
183188 inst . _zod . version = version ;
189+ inst . _zod . getJSONSchema = ( _ctx ?: JSONSchemaContext ) => {
190+ throw new Error ( `Unsupported JSON Schema conversion for type "${ def . type } "` ) ;
191+ } ;
184192
185193 const checks = [ ...( inst . _zod . def . checks ?? [ ] ) ] ;
186194
@@ -353,6 +361,26 @@ export interface $ZodString<Input = unknown> extends _$ZodType<$ZodStringInterna
353361export const $ZodString : core . $constructor < $ZodString > = /*@__PURE__ */ core . $constructor ( "$ZodString" , ( inst , def ) => {
354362 $ZodType . init ( inst , def ) ;
355363 inst . _zod . pattern = [ ...( inst ?. _zod . bag ?. patterns ?? [ ] ) ] . pop ( ) ?? regexes . string ( inst . _zod . bag ) ;
364+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
365+ createJSONSchema < JSONSchema . StringSchema > ( inst , ctx , ( json ) => {
366+ json . type = "string" ;
367+ const bag = inst . _zod . bag as $ZodStringInternals < unknown > [ "bag" ] ;
368+ if ( typeof bag . minimum === "number" ) json . minLength = bag . minimum ;
369+ if ( typeof bag . maximum === "number" ) json . maxLength = bag . maximum ;
370+ const format = bag . format as checks . $ZodStringFormats | string | undefined ;
371+ if ( typeof format === "string" ) {
372+ const mapped = stringFormatMap [ format as checks . $ZodStringFormats ] ;
373+ if ( mapped !== undefined ) json . format = mapped ;
374+ else json . format = format ;
375+ }
376+ if ( bag . patterns ?. size ) {
377+ const [ pattern ] = bag . patterns ;
378+ if ( pattern ) json . pattern = pattern . source ;
379+ }
380+ if ( typeof bag . contentEncoding === "string" ) {
381+ json . contentEncoding = bag . contentEncoding ;
382+ }
383+ } ) ;
356384 inst . _zod . parse = ( payload , _ ) => {
357385 if ( def . coerce )
358386 try {
@@ -1066,6 +1094,20 @@ export interface $ZodNumber<Input = unknown> extends $ZodType {
10661094export const $ZodNumber : core . $constructor < $ZodNumber > = /*@__PURE__ */ core . $constructor ( "$ZodNumber" , ( inst , def ) => {
10671095 $ZodType . init ( inst , def ) ;
10681096 inst . _zod . pattern = inst . _zod . bag . pattern ?? regexes . number ;
1097+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
1098+ createJSONSchema < JSONSchema . NumberSchema | JSONSchema . IntegerSchema > ( inst , ctx , ( json ) => {
1099+ const bag = inst . _zod . bag as $ZodNumberInternals < unknown > [ "bag" ] & {
1100+ multipleOf ?: number ;
1101+ } ;
1102+ const format = bag ?. format ;
1103+ json . type = typeof format === "string" && format . includes ( "int" ) ? "integer" : "number" ;
1104+ if ( typeof bag ?. minimum === "number" ) json . minimum = bag . minimum ;
1105+ if ( typeof bag ?. maximum === "number" ) json . maximum = bag . maximum ;
1106+ if ( typeof bag ?. exclusiveMinimum === "number" ) json . exclusiveMinimum = bag . exclusiveMinimum ;
1107+ if ( typeof bag ?. exclusiveMaximum === "number" ) json . exclusiveMaximum = bag . exclusiveMaximum ;
1108+ if ( typeof bag ?. multipleOf === "number" ) json . multipleOf = bag . multipleOf ;
1109+ if ( typeof format === "string" ) json . format = format ;
1110+ } ) ;
10691111
10701112 inst . _zod . parse = ( payload , _ctx ) => {
10711113 if ( def . coerce )
@@ -1149,6 +1191,10 @@ export const $ZodBoolean: core.$constructor<$ZodBoolean> = /*@__PURE__*/ core.$c
11491191 ( inst , def ) => {
11501192 $ZodType . init ( inst , def ) ;
11511193 inst . _zod . pattern = regexes . boolean ;
1194+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
1195+ createJSONSchema < JSONSchema . BooleanSchema > ( inst , ctx , ( json ) => {
1196+ json . type = "boolean" ;
1197+ } ) ;
11521198
11531199 inst . _zod . parse = ( payload , _ctx ) => {
11541200 if ( def . coerce )
@@ -1202,6 +1248,17 @@ export interface $ZodBigInt<T = unknown> extends $ZodType {
12021248export const $ZodBigInt : core . $constructor < $ZodBigInt > = /*@__PURE__ */ core . $constructor ( "$ZodBigInt" , ( inst , def ) => {
12031249 $ZodType . init ( inst , def ) ;
12041250 inst . _zod . pattern = regexes . bigint ;
1251+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
1252+ createJSONSchema < JSONSchema . IntegerSchema > ( inst , ctx , ( json ) => {
1253+ json . type = "integer" ;
1254+ const bag = inst . _zod . bag as $ZodBigIntInternals < unknown > [ "bag" ] & {
1255+ minimum ?: bigint ;
1256+ maximum ?: bigint ;
1257+ } ;
1258+ if ( typeof bag ?. format === "string" ) json . format = bag . format ;
1259+ if ( typeof bag ?. minimum === "bigint" ) json . minimum = Number ( bag . minimum ) ;
1260+ if ( typeof bag ?. maximum === "bigint" ) json . maximum = Number ( bag . maximum ) ;
1261+ } ) ;
12051262
12061263 inst . _zod . parse = ( payload , _ctx ) => {
12071264 if ( def . coerce )
@@ -1354,6 +1411,10 @@ export const $ZodNull: core.$constructor<$ZodNull> = /*@__PURE__*/ core.$constru
13541411 $ZodType . init ( inst , def ) ;
13551412 inst . _zod . pattern = regexes . null ;
13561413 inst . _zod . values = new Set ( [ null ] ) ;
1414+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
1415+ createJSONSchema < JSONSchema . NullSchema > ( inst , ctx , ( json ) => {
1416+ json . type = "null" ;
1417+ } ) ;
13571418
13581419 inst . _zod . parse = ( payload , _ctx ) => {
13591420 const input = payload . value ;
@@ -1392,6 +1453,7 @@ export interface $ZodAny extends $ZodType {
13921453
13931454export const $ZodAny : core . $constructor < $ZodAny > = /*@__PURE__ */ core . $constructor ( "$ZodAny" , ( inst , def ) => {
13941455 $ZodType . init ( inst , def ) ;
1456+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) => createJSONSchema < JSONSchema . BaseSchema > ( inst , ctx , ( ) => { } ) ;
13951457
13961458 inst . _zod . parse = ( payload ) => payload ;
13971459} ) ;
@@ -1421,6 +1483,7 @@ export const $ZodUnknown: core.$constructor<$ZodUnknown> = /*@__PURE__*/ core.$c
14211483 "$ZodUnknown" ,
14221484 ( inst , def ) => {
14231485 $ZodType . init ( inst , def ) ;
1486+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) => createJSONSchema < JSONSchema . BaseSchema > ( inst , ctx , ( ) => { } ) ;
14241487
14251488 inst . _zod . parse = ( payload ) => payload ;
14261489 }
@@ -1527,6 +1590,13 @@ export interface $ZodDate<T = unknown> extends $ZodType {
15271590
15281591export const $ZodDate : core . $constructor < $ZodDate > = /*@__PURE__ */ core . $constructor ( "$ZodDate" , ( inst , def ) => {
15291592 $ZodType . init ( inst , def ) ;
1593+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
1594+ createJSONSchema < JSONSchema . StringSchema > ( inst , ctx , ( json ) => {
1595+ json . type = "string" ;
1596+ json . format = "date-time" ;
1597+ const bag = inst . _zod . bag as $ZodDateInternals < unknown > [ "bag" ] ;
1598+ if ( bag ?. format ) json . format = bag . format ;
1599+ } ) ;
15301600
15311601 inst . _zod . parse = ( payload , _ctx ) => {
15321602 if ( def . coerce ) {
@@ -1584,6 +1654,14 @@ function handleArrayResult(result: ParsePayload<any>, final: ParsePayload<any[]>
15841654
15851655export const $ZodArray : core . $constructor < $ZodArray > = /*@__PURE__ */ core . $constructor ( "$ZodArray" , ( inst , def ) => {
15861656 $ZodType . init ( inst , def ) ;
1657+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
1658+ createJSONSchema < JSONSchema . ArraySchema > ( inst , ctx , ( json , context ) => {
1659+ json . type = "array" ;
1660+ json . items = def . element . _zod . getJSONSchema ( context ) ;
1661+ const bag = inst . _zod . bag as { minimum ?: number ; maximum ?: number } ;
1662+ if ( typeof bag ?. minimum === "number" ) json . minItems = bag . minimum ;
1663+ if ( typeof bag ?. maximum === "number" ) json . maxItems = bag . maximum ;
1664+ } ) ;
15871665
15881666 inst . _zod . parse = ( payload , ctx ) => {
15891667 const input = payload . value ;
@@ -1825,6 +1903,26 @@ function handleCatchall(
18251903export const $ZodObject : core . $constructor < $ZodObject > = /*@__PURE__ */ core . $constructor ( "$ZodObject" , ( inst , def ) => {
18261904 // requires cast because technically $ZodObject doesn't extend
18271905 $ZodType . init ( inst , def ) ;
1906+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
1907+ createJSONSchema < JSONSchema . ObjectSchema > ( inst , ctx , ( json , context ) => {
1908+ json . type = "object" ;
1909+ const shape = def . shape as $ZodShape ;
1910+ const properties : Record < string , JSONSchema . BaseSchema > = { } ;
1911+ const required : string [ ] = [ ] ;
1912+ for ( const key of Object . keys ( shape ) ) {
1913+ const child = shape [ key ] ! ;
1914+ properties [ key ] = child . _zod . getJSONSchema ( context ) ;
1915+ if ( child . _zod . optin !== "optional" ) {
1916+ required . push ( key ) ;
1917+ }
1918+ }
1919+ if ( Object . keys ( properties ) . length ) json . properties = properties ;
1920+ if ( required . length ) json . required = required ;
1921+ const catchall = def . catchall as $ZodType | undefined ;
1922+ if ( catchall ) {
1923+ json . additionalProperties = catchall . _zod . def . type === "never" ? false : catchall . _zod . getJSONSchema ( context ) ;
1924+ }
1925+ } ) ;
18281926 // const sh = def.shape;
18291927 const desc = Object . getOwnPropertyDescriptor ( def , "shape" ) ;
18301928 if ( ! desc ?. get ) {
@@ -2055,6 +2153,10 @@ function handleUnionResults(results: ParsePayload[], final: ParsePayload, inst:
20552153
20562154export const $ZodUnion : core . $constructor < $ZodUnion > = /*@__PURE__ */ core . $constructor ( "$ZodUnion" , ( inst , def ) => {
20572155 $ZodType . init ( inst , def ) ;
2156+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
2157+ createJSONSchema < JSONSchema . BaseSchema > ( inst , ctx , ( json , context ) => {
2158+ json . anyOf = def . options . map ( ( option ) => option . _zod . getJSONSchema ( context ) ) ;
2159+ } ) ;
20582160
20592161 util . defineLazy ( inst . _zod , "optin" , ( ) =>
20602162 def . options . some ( ( o ) => o . _zod . optin === "optional" ) ? "optional" : undefined
@@ -2419,6 +2521,17 @@ export interface $ZodTuple<
24192521
24202522export const $ZodTuple : core . $constructor < $ZodTuple > = /*@__PURE__ */ core . $constructor ( "$ZodTuple" , ( inst , def ) => {
24212523 $ZodType . init ( inst , def ) ;
2524+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
2525+ createJSONSchema < JSONSchema . ArraySchema > ( inst , ctx , ( json , context ) => {
2526+ json . type = "array" ;
2527+ const items = def . items . map ( ( item ) => item . _zod . getJSONSchema ( context ) ) ;
2528+ if ( items . length ) json . prefixItems = items ;
2529+ if ( def . rest ) json . items = def . rest . _zod . getJSONSchema ( context ) ;
2530+ else json . items = false ;
2531+ const required = def . items . filter ( ( item ) => item . _zod . optin !== "optional" ) . length ;
2532+ if ( required ) json . minItems = required ;
2533+ if ( ! def . rest ) json . maxItems = def . items . length ;
2534+ } ) ;
24222535 const items = def . items ;
24232536 const optStart = items . length - [ ...items ] . reverse ( ) . findIndex ( ( item ) => item . _zod . optin !== "optional" ) ;
24242537
@@ -2573,6 +2686,12 @@ export interface $ZodRecord<Key extends $ZodRecordKey = $ZodRecordKey, Value ext
25732686
25742687export const $ZodRecord : core . $constructor < $ZodRecord > = /*@__PURE__ */ core . $constructor ( "$ZodRecord" , ( inst , def ) => {
25752688 $ZodType . init ( inst , def ) ;
2689+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
2690+ createJSONSchema < JSONSchema . ObjectSchema > ( inst , ctx , ( json , context ) => {
2691+ json . type = "object" ;
2692+ json . additionalProperties = def . valueType . _zod . getJSONSchema ( context ) ;
2693+ json . propertyNames = def . keyType . _zod . getJSONSchema ( context ) ;
2694+ } ) ;
25762695
25772696 inst . _zod . parse = ( payload , ctx ) => {
25782697 const input = payload . value ;
@@ -2893,6 +3012,13 @@ export const $ZodEnum: core.$constructor<$ZodEnum> = /*@__PURE__*/ core.$constru
28933012 . map ( ( o ) => ( typeof o === "string" ? util . escapeRegex ( o ) : o . toString ( ) ) )
28943013 . join ( "|" ) } )$`
28953014 ) ;
3015+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
3016+ createJSONSchema < JSONSchema . BaseSchema > ( inst , ctx , ( json ) => {
3017+ const list = Array . from ( inst . _zod . values ?? [ ] ) ;
3018+ if ( list . length ) {
3019+ json . enum = list as Array < string | number | boolean | null > ;
3020+ }
3021+ } ) ;
28963022
28973023 inst . _zod . parse = ( payload , _ctx ) => {
28983024 const input = payload . value ;
@@ -2949,6 +3075,11 @@ export const $ZodLiteral: core.$constructor<$ZodLiteral> = /*@__PURE__*/ core.$c
29493075 . map ( ( o ) => ( typeof o === "string" ? util . escapeRegex ( o ) : o ? util . escapeRegex ( o . toString ( ) ) : String ( o ) ) )
29503076 . join ( "|" ) } )$`
29513077 ) ;
3078+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
3079+ createJSONSchema < JSONSchema . BaseSchema > ( inst , ctx , ( json ) => {
3080+ const list = Array . from ( inst . _zod . values ) as Array < string | number | boolean | null > ;
3081+ json . enum = list ;
3082+ } ) ;
29523083
29533084 inst . _zod . parse = ( payload , _ctx ) => {
29543085 const input = payload . value ;
@@ -3146,6 +3277,11 @@ export const $ZodOptional: core.$constructor<$ZodOptional> = /*@__PURE__*/ core.
31463277 ( inst , def ) => {
31473278 $ZodType . init ( inst , def ) ;
31483279 inst . _zod . optin = "optional" ;
3280+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
3281+ createJSONSchema < JSONSchema . BaseSchema > ( inst , ctx , ( json , context ) => {
3282+ const inner = def . innerType . _zod . getJSONSchema ( context ) ;
3283+ Object . assign ( json , inner ) ;
3284+ } ) ;
31493285 inst . _zod . optout = "optional" ;
31503286
31513287 util . defineLazy ( inst . _zod , "values" , ( ) => {
@@ -3200,6 +3336,11 @@ export const $ZodNullable: core.$constructor<$ZodNullable> = /*@__PURE__*/ core.
32003336 "$ZodNullable" ,
32013337 ( inst , def ) => {
32023338 $ZodType . init ( inst , def ) ;
3339+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
3340+ createJSONSchema < JSONSchema . BaseSchema > ( inst , ctx , ( json , context ) => {
3341+ const inner = def . innerType . _zod . getJSONSchema ( context ) ;
3342+ json . anyOf = [ inner , { type : "null" } ] ;
3343+ } ) ;
32033344 util . defineLazy ( inst . _zod , "optin" , ( ) => def . innerType . _zod . optin ) ;
32043345 util . defineLazy ( inst . _zod , "optout" , ( ) => def . innerType . _zod . optout ) ;
32053346
@@ -3255,6 +3396,13 @@ export const $ZodDefault: core.$constructor<$ZodDefault> = /*@__PURE__*/ core.$c
32553396
32563397 // inst._zod.qin = "true";
32573398 inst . _zod . optin = "optional" ;
3399+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
3400+ createJSONSchema < JSONSchema . BaseSchema > ( inst , ctx , ( json , context ) => {
3401+ const inner = def . innerType . _zod . getJSONSchema ( context ) ;
3402+ Object . assign ( json , inner ) ;
3403+ const value = def . defaultValue ;
3404+ json . default = typeof value === "function" ? value ( ) : value ;
3405+ } ) ;
32583406 util . defineLazy ( inst . _zod , "values" , ( ) => def . innerType . _zod . values ) ;
32593407
32603408 inst . _zod . parse = ( payload , ctx ) => {
@@ -4163,6 +4311,11 @@ export interface $ZodLazy<T extends SomeType = $ZodType> extends $ZodType {
41634311
41644312export const $ZodLazy : core . $constructor < $ZodLazy > = /*@__PURE__ */ core . $constructor ( "$ZodLazy" , ( inst , def ) => {
41654313 $ZodType . init ( inst , def ) ;
4314+ inst . _zod . getJSONSchema = ( ctx ?: JSONSchemaContext ) =>
4315+ createJSONSchema < JSONSchema . BaseSchema > ( inst , ctx , ( json , context ) => {
4316+ const resolved = inst . _zod . innerType . _zod . getJSONSchema ( context ) ;
4317+ Object . assign ( json , resolved ) ;
4318+ } ) ;
41664319
41674320 // let _innerType!: any;
41684321 // util.defineLazy(def, "getter", () => {
0 commit comments