StefanTerdell / zod-to-json-schema

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

Represent `Map`s as records #89

Closed MOZGIII closed 9 months ago

MOZGIII commented 11 months ago

Maps are not handled properly. They can't be parsed directly from JSON, so it is not clear how to represent them. Currently, they are represented as [K, V][], but it would be great to have the ability to use { [K]: V } instead. It matters not that K must always be a string with this representation, since zod has a neat z.preprocess feature to fix it before parsing.

StefanTerdell commented 9 months ago

Maps are not handled properly

it is not clear how to represent them

Pick one :)

It doesn't matter that it has a preprocess if it can't be guaranteed to be used all the time.

MOZGIII commented 9 months ago

Pick one :)

Ok, fair.

It doesn't matter that it has a preprocess if it can't be guaranteed to be used all the time.

I'd be fine with an opt-in, since either way we build schema explicitly - maybe we could just have a configuration option?

MOZGIII commented 9 months ago

I ended up using this hack:

const coercedMap = <K extends ZodTypeAny, V extends ZodTypeAny>(
  keySchema: K,
  valueSchema: V,
) =>
  z.preprocess(
  (arg, ctx) =>
      arg === undefined
        ? new Map()
        : new Map(
            Object.entries(arg as {}).map(([key, val]) => [
              keySchema.parse(key, {
                path: [...ctx.path, key, "<key>"],
              }),
              val,
            ]),
          ),
    // For JSON Schemas pretend we are an object rather than a map.
    tweaks.jsonSchemaHack
      ? (z.record(keySchema, valueSchema) as never)
      : z.map(keySchema, valueSchema),
  );

tweaks.jsonSchemaHack is a global that is toggled on when we export schemas, but is off for everything else.

What I'm looking for is to get rid of the tweaks.jsonSchemaHack - if it was possible to just tell zod-to-json-schema I am using z.map but I want it to look like a z.record that would be great.

StefanTerdell commented 9 months ago

Sure, wth.

StefanTerdell commented 9 months ago

Done in master

MOZGIII commented 9 months ago

Sweet! Thanks!