StefanTerdell / zod-to-json-schema

Converts Zod schemas to Json schemas
ISC License
854 stars 67 forks source link

Support `readonly()` #90

Closed thorhj closed 9 months ago

thorhj commented 11 months ago

With zod 3.22.0+ we now have .readonly() which can be applied to various types, most notably array and object. This is not supported in zod-to-json-schema yet, so it just returns an empty schema:

import { z } from "zod";
import zodToJsonSchema from "zod-to-json-schema";

const schema = z.object({
  foo: z.boolean(),
  bar: z.number(),
});

console.log("Regular types:");
console.log(zodToJsonSchema(schema));
console.log(zodToJsonSchema(schema.array()));

console.log();
console.log("Readonly types:");
console.log(zodToJsonSchema(schema.readonly()));
console.log(zodToJsonSchema(schema.array().readonly()));
Regular types:
{
  type: 'object',
  properties: { foo: { type: 'boolean' }, bar: { type: 'number' } },
  required: [ 'foo', 'bar' ],
  additionalProperties: false,
  '$schema': 'http://json-schema.org/draft-07/schema#'
}
{
  type: 'array',
  items: {
    type: 'object',
    properties: { foo: [Object], bar: [Object] },
    required: [ 'foo', 'bar' ],
    additionalProperties: false
  },
  '$schema': 'http://json-schema.org/draft-07/schema#'
}

Readonly types:
{ '$schema': 'http://json-schema.org/draft-07/schema#' }
{ '$schema': 'http://json-schema.org/draft-07/schema#' }
kachkaev commented 11 months ago

Same issue here. Does readonly() affect the result or is it a ‘transparent’ definition , like .catch()?

https://github.com/StefanTerdell/zod-to-json-schema/blob/b8f2ac75ee19def713af444e9fff42e3817ba3e4/src/parsers/catch.ts#L1-L7

If it’s the latter, supporting .readonly() should be pretty straightforward. Happy to submit a PR if it makes sense.


UPD: This local patch seems to be working – I no longer get empty schemas 🎉

diff --git a/src/parseDef.js b/src/parseDef.js
index 4f33785322590999d31593cdcbdb174175930799..f8a09be4387cd64c1534f1f3a2a6c70f4625e1f2 100644
--- a/src/parseDef.js
+++ b/src/parseDef.js
@@ -151,6 +151,8 @@ const selectParser = (def, typeName, refs) => {
         case zod_1.ZodFirstPartyTypeKind.ZodBranded:
             return (0, branded_1.parseBrandedDef)(def, refs);
         case zod_1.ZodFirstPartyTypeKind.ZodCatch:
+        // https://github.com/StefanTerdell/zod-to-json-schema/issues/90
+        case zod_1.ZodFirstPartyTypeKind.ZodReadonly:
             return (0, catch_1.parseCatchDef)(def, refs);
         case zod_1.ZodFirstPartyTypeKind.ZodPipeline:
             return (0, pipeline_1.parsePipelineDef)(def, refs);

For simplicity, ZodReadonly is processed the same way as ZodCatch.

StefanTerdell commented 9 months ago

Done in master

fredrikj31 commented 9 months ago

When is this gonna be released @StefanTerdell ?

StefanTerdell commented 9 months ago

@fredrikj31 about a minute ago

kachkaev commented 9 months ago

Great, thanks @StefanTerdell! The new version works like a charm ✨

If you have a bit of time, can you please update the list of releases?

It should help Renovate (and other similar tools) show the list changes in autogenerated PRs. It is empty at the moment:

Screenshot 2023-11-18 at 11 58 20