Vai al contenuto

Trasformatore da schema JSON a schema Zod — Numio

Genera codice di convalida Zod da un JSON Schema con json-schema-to-zod. Vincoli come minLength, minimum, pattern e default diventano metodi Zod concatenati; le proprietà non elencate in "required" ricevono .optional().

Ricevi uno schema JSON da un altro team e desideri la convalida del runtime in un servizio TypeScript senza un validatore dello schema JSON.

JSON Schema

Zod Schema

Quando usarlo

  • Ricevi uno schema JSON da un altro team e desideri la convalida del runtime in un servizio TypeScript senza un validatore dello schema JSON.
  • Stai spostando la convalida del modulo da un validatore di schema JSON come Ajv a Zod e desideri che il codice generato inizi da.

Come si usa

  1. Incolla uno schema JSON nel pannello Schema JSON.
  2. Facoltativamente aprire le impostazioni e modificare il nome dello schema root ("schema" predefinito); diventa il nome del const esportato.
  3. Copia il codice generato, che importa z da "zod", nel tuo progetto. La conversione viene eseguita nel browser.

Schema JSON

{
  "type": "object",
  "properties": {
    "username": { "type": "string", "minLength": 3, "maxLength": 20 },
    "age": { "type": "integer", "minimum": 18 },
    "contact": {
      "oneOf": [
        { "type": "string", "format": "email" },
        { "type": "string", "pattern": "^\\+[0-9]+$" }
      ]
    },
    "newsletter": { "type": "boolean", "default": false }
  },
  "required": ["username", "contact"]
}

Schema Zod

import { z } from "zod"

export const schema = z.object({
  username: z.string().min(3).max(20),
  age: z.number().int().gte(18).optional(),
  contact: z.any().superRefine((x, ctx) => {
    const schemas = [
      z.string().email(),
      z.string().regex(new RegExp("^\\+[0-9]+$")),
    ]
    const errors = schemas.reduce(
      (errors: z.ZodError[], schema) =>
        ((result) => ("error" in result ? [...errors, result.error] : errors))(
          schema.safeParse(x),
        ),
      [],
    )
    if (schemas.length - errors.length !== 1) {
      ctx.addIssue({
        path: ctx.path,
        code: "invalid_union",
        unionErrors: errors,
        message: "Invalid input: Should pass single schema",
      })
…

Dettagli e limiti

oneOf viene convertito in z.any().superRefine(...), che verifica che venga superato esattamente un sottoschema, come mostra l'esempio.

$ref non è stato risolto: una proprietà a cui si fa riferimento diventa z.any().

integer aggiunge .int(), format "email" aggiunge .email() e format "date-time" aggiunge .datetime().

additionalProperties: false diventa .catchall(z.never()) invece di .strict().

FAQ

Come vengono gestiti i tipi nullable?

"type": ["string", "null"] diventa z.union([z.string(), z.null()]), con .optional() aggiunto se la proprietà non è richiesta.

Posso rinominare lo schema esportato?

Sì. Imposta il nome dello schema root nelle impostazioni; l'output legge quindi export const <name> = ... invece di export const schema.

Sono supportate le definizioni e $ref?

No. Una proprietà che utilizza $ref diventa z.any(), quindi incorpora lo schema di riferimento prima della conversione.

Specifiche e riferimenti