Closed maRci002 closed 2 months ago
I see that the nullable parser can exhibit this behavior when the target is set to 'openApi3'
, however, this might have unintended consequences.
import { z } from 'zod';
import { schemaToJsonSchema } from 'zod-to-json-schema';
const zodSchema = z.object({
name: z.string().nullable(),
age: z.number().nullable(),
});
const jsonSchema = schemaToJsonSchema(zodSchema, { target: 'openApi3' });
console.log(jsonSchema);
Fastify does not accept the current implementation when '$ref' is used #103
{
"type": "FastifyError",
"message": "Failed building the validation schema for POST: /v1/equipments, due to error \"nullable\" cannot be used without \"type\""
}
This won't throw error, however actual Fastify will:
import { z } from 'zod';
import { zodToJsonSchema } from 'zod-to-json-schema';
import fastJson from 'fast-json-stringify';
const snippet = z.object({
username: z.string(),
});
const profileModelZod = z.object({
snippet: snippet,
snippet2: snippet.nullable(),
});
const profileSchema = zodToJsonSchema(profileModelZod, { target: 'openApi3' });
console.log(JSON.stringify(profileSchema, null, 2));
const profile = {
snippet: {
username: '',
additionalProperty: '',
},
snippet2: null,
};
type ZodToJsonSchemaOptions = Parameters<typeof fastJson>[0];
const optionalStringify = fastJson(profileSchema as ZodToJsonSchemaOptions);
console.log(optionalStringify(profile)); // ok
Output schema:
{
"type": "object",
"properties": {
"snippet": {
"type": "object",
"properties": {
"username": {
"type": "string"
}
},
"required": [
"username"
],
"additionalProperties": false
},
"snippet2": {
"allOf": [
{
"$ref": "#/properties/snippet"
}
],
"nullable": true
}
},
"required": [
"snippet",
"snippet2"
],
"additionalProperties": false
}
FYI, nullable
has been removed from OpenAPI 3, and they suggest first registering the most pessimistic version of my schema and then adding further constraints to it.
I hope this package will support this feature soon. Until then, I'm using $refStrategy: 'none'
as a workaround.
Currently, when using zod-to-json-schema to convert Zod schemas that include nullable types using .nullable(), the output utilizes the anyOf construct in the generated JSON Schema. For instance, converting z.string().nullable() results in a schema that looks like this:
???
The output from your example would literally be { type: ["string", "null"] }
. As long as the schema is a primitive without checks the output will follow this pattern, except when the target is "OpenAPI3" (which really should be called "OpenAPI3.0"), because it doesn't support it.
The thing is Open API 3.1 includes the full Json Schema spec so you don't have to use the specific target for it. If anything, this issue is probably related to the lack of documentation of that fact.
fast-json-stringify documentation highlights the performance impact of using anyOf and oneOf, noting that these constructs should be used as a last resort due to the performance penalty involved in validating multiple schemas. Here's an excerpt from their documentation:
Performance has never been the top consideration for this package, or Zod for that matter.
Fastify does not accept the current implementation when '$ref' is used https://github.com/StefanTerdell/zod-to-json-schema/issues/103
That's a Fastify problem.
FYI, nullable https://github.com/OAI/OpenAPI-Specification/issues/1368#issuecomment-2347085147 from OpenAPI 3, and they suggest first registering the most pessimistic version of my schema and then https://github.com/OAI/OpenAPI-Specification/issues/1368#issuecomment-2347873811 to it.
As mentioned above, that's a misconception. Open API 3.0 has not removed nullable, but Open API 3.1 includes the full Json Schema spec, so you don't need to use the specific target at all if you can use that.
Description
Currently, when using
zod-to-json-schema
to convert Zod schemas that include nullable types using.nullable()
, the output utilizes theanyOf
construct in the generated JSON Schema. For instance, convertingz.string().nullable()
results in a schema that looks like this:However, for certain applications and tools, it would be beneficial to have an option to output nullable types using the combined type array syntax, such as
"type": ["string", "null"]
. This syntax is more concise and can be easier to handle for some JSON Schema validators and UI schema generators.Feature Request
I propose adding an option or configuration setting in
zod-to-json-schema
that allows users to specify the desired format for nullable types. Ideally, this would let users choose between the existinganyOf
format and a new array format for types. For example:This could output:
Use Case
This feature would be particularly useful for developers who are integrating with JSON Schema consumers that expect the
"type": ["string", "null"]
format, which can occur in various API clients and documentation tools. The simpler array format is also generally more concise and could potentially simplify schema validation logic in certain scenarios.Performance Context from
fast-json-stringify
fast-json-stringify
documentation highlights the performance impact of usinganyOf
andoneOf
, noting that these constructs should be used as a last resort due to the performance penalty involved in validating multiple schemas. Here's an excerpt from their documentation:For more details, you can view their documentation here.