Generate Zod Union Types from Mixed JSON Arrays

Learn how to create Zod discriminated unions and regular unions from JSON arrays containing objects with different shapes.

Arrays

Detailed Explanation

Union Types in Zod

When a JSON array contains objects with different shapes, Zod provides z.union() and z.discriminatedUnion() to validate each variant correctly.

Example JSON

[
  { "type": "text", "content": "Hello world" },
  { "type": "image", "url": "https://cdn.example.com/photo.jpg", "alt": "A photo" },
  { "type": "video", "url": "https://cdn.example.com/clip.mp4", "duration": 120 }
]

Discriminated Union Schema

import { z } from "zod";

const textBlockSchema = z.object({
  type: z.literal("text"),
  content: z.string(),
});

const imageBlockSchema = z.object({
  type: z.literal("image"),
  url: z.string(),
  alt: z.string(),
});

const videoBlockSchema = z.object({
  type: z.literal("video"),
  url: z.string(),
  duration: z.number(),
});

const blockSchema = z.discriminatedUnion("type", [
  textBlockSchema,
  imageBlockSchema,
  videoBlockSchema,
]);

type Block = z.infer<typeof blockSchema>;

discriminatedUnion vs union

z.discriminatedUnion() is faster and produces better error messages than z.union() because it uses the discriminant field to select the correct schema immediately, rather than trying each option.

Feature z.union() z.discriminatedUnion()
Requires shared key No Yes
Performance Tries each option Direct lookup
Error messages Generic Points to discriminant
Best for Primitive unions Object variants

When to Use Each

  • z.discriminatedUnion() — Objects that share a common tag field (like type, kind, action).
  • z.union() — Primitive type unions or objects without a shared discriminant.

Example: Simple Union

// For primitives or objects without a discriminant
const idSchema = z.union([z.string(), z.number()]);
// Accepts either a string ID or numeric ID

Using discriminated unions is one of Zod's most powerful patterns for validating polymorphic API responses.

Use Case

You are building a rich content editor where the API returns an array of heterogeneous blocks (text, image, video) and you need validated, type-safe rendering logic for each variant.

Try It — JSON to Zod Schema

Open full tool