Skip to main content
Lesson 7 of 12 · Structured JSON Outputs

Zod with JavaScript

Lesson 7 of 12 Updated July 30, 2026 Developer
On this page
  1. Structured outputs in JavaScript
  2. Installation
  3. Client configuration
  4. Defining a schema with Zod
  5. Type mapping
  6. Complete example
  7. Nested schemas
  8. Optional fields with nullable
  9. Client-side validation
  10. Key takeaways

Structured outputs in JavaScript

If you’re developing in JavaScript or TypeScript, Zod is the equivalent of Pydantic. This schema validation library integrates seamlessly with the Grok API to produce typed structured outputs.

Installation

npm install zod openai

The OpenAI SDK for JavaScript works directly with the Grok API—you just need to point it to the correct endpoint.

Client configuration

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "your-xai-key",
  baseURL: "https://api.x.ai/v1"
});

Defining a schema with Zod

Zod uses a fluent API to define schemas. Each method maps to a JSON type:

import { z } from "zod";

const MovieReview = z.object({
  title: z.string(),
  rating: z.number(),
  summary: z.string(),
  recommend: z.boolean()
});

Type mapping

ZodJSON SchemaPydantic (Python)
z.string()"type": "string"str
z.number()"type": "number"float
z.boolean()"type": "boolean"bool
z.array(z.string())array of stringslist[str]
z.object({...})"type": "object"BaseModel
z.enum([...])enumLiteral[...]
z.union([...])anyOfUnion types
z.nullable()anyOf with nullstr | None

Complete example

import OpenAI from "openai";
import { z } from "zod";

const client = new OpenAI({
  apiKey: "your-xai-key",
  baseURL: "https://api.x.ai/v1"
});

const Analyse = z.object({
  titre: z.string(),
  resume: z.string(),
  sentiment: z.enum(["positif", "negatif", "neutre"]),
  score: z.number(),
  mots_cles: z.array(z.string()),
  recommandation: z.boolean()
});

const response = await client.chat.completions.create({
  model: "grok-4.20-0309-reasoning",
  messages: [{
    role: "user",
    content: "Analyze the following text: Sales increased by 25% this quarter."
  }],
  response_format: {
    type: "json_schema",
    json_schema: {
      name: "analyse",
      schema: Analyse
    }
  }
});

const data = JSON.parse(response.choices[0].message.content);
console.log(data.sentiment);  // "positive"
console.log(data.score);      // 0.92

Nested schemas

Like Pydantic, Zod handles nesting naturally:

const Adresse = z.object({
  rue: z.string(),
  ville: z.string(),
  code_postal: z.string(),
  pays: z.string()
});

const Contact = z.object({
  nom: z.string(),
  email: z.string(),
  telephone: z.string().nullable(),
  adresse: Adresse,
  tags: z.array(z.string())
});

Optional fields with nullable

To make a field optional (able to be null), use .nullable():

const Produit = z.object({
  nom: z.string(),
  prix: z.number(),
  description: z.string().nullable(),
  promotion: z.number().nullable()
});

Client-side validation

One advantage of Zod is that you can validate data client-side using the same schema:

const rawData = JSON.parse(response.choices[0].message.content);

// Validation with Zod
const result = Analyse.safeParse(rawData);

if (result.success) {
  console.log(result.data.titre);
} else {
  console.error("Validation error:", result.error);
}

In practice, validation will always succeed because the API guarantees schema compliance. However, this additional layer is useful for robustness in production.

Key takeaways

  • Zod is the JavaScript/TypeScript equivalent of Pydantic
  • The syntax is fluent: z.string(), z.number(), z.object({...})
  • .nullable() makes a field optional (can be null)
  • Pass Zod schemas in response_format.json_schema.schema
  • safeParse() enables defensive client-side validation
  • The OpenAI SDK for JavaScript works directly with the Grok API