moon_zod/docs/en/EXAMPLES.md

15 KiB

Examples

moon_zod ships with a variety of examples demonstrating different use cases, from basic JSON validation to full LLM tool-calling self-correction loops.

Quick Overview

Example Description Output
json2schema Define schemas in MoonBit + validate hardcoded JSON Prints validation results for User, Post, and GitHub API schemas
mock/llm_agent Simulated LLM self-correction loop (simple) 2-round mock: bad JSON → errors → fixed JSON → Strip cleanse
mock/educational_agent Simulated 3-round self-correction (deep) 3 rounds: structural → rule → Strip defense layers
multiple_schemas Schema composition + multi-format code gen Outputs TS / JSON Schema / MoonBit struct / moon_zod code
real_llm_agent End-to-end Schema → Prompt → Real LLM → Parse Self-correction loop: validate → collect errors → retry
schema2json moon_zod schema → JSON Schema export Standard JSON Schema with full constraints
schema2prompt moon_zod schema → TS interface prompt TypeScript interface with // constraint comments
validate CLI JSON Schema → validate JSON PASS / FAIL with error details
gen-struct CLI JSON Schema → MoonBit struct code gen pub struct + fn to_schema() definitions
json2schema CLI JSON → moon_zod schema code gen Copy-paste ready @moon_zod.object({...}) code

json2schema

Path: examples/json2schema/README

A runnable MoonBit program that defines realistic schemas (JSONPlaceholder user, post, GitHub Rust repo API response) and validates hardcoded JSON against them. Prints success/failure for each schema.

$ sh cmd/json2schema/cli.sh --file examples/resources/test_placeholder_post.json

Output:

let root = @moon_zod.object({ "userId": @moon_zod.number().int(), "id": @moon_zod.number().int(), "title": @moon_zod.string(), "body": @moon_zod.string() }).name("Root")

mock

Path: examples/mock/README

mock/llm_agent

Simulated self-correction loop for a user-profile schema. Mock LLM first returns invalid JSON — moon_zod collects all errors. After correction feedback, mock LLM retries with valid data plus a hallucinated field. Strip mode silently removes it.

$ moon run examples/mock/llm_agent

Output be like:

── Round 1 ──────────────────────────
  Mock LLM output (bad): { "name": 123, "role": "superadmin" }
  Errors:
    [name] Expected string (got: 123)
    [role] Invalid enum value (got: "superadmin")
── Round 2 ──────────────────────────
  Mock LLM output (fixed + hallucination): { "name": "Alice", "role": "admin", "hacked": true }
  ✅ VALIDATION PASSED (Strip mode: "hacked" removed)

mock/educational_agent

3-round simulation for a course schema, demonstrating moon_zod's three-layer defense:

Round Defense Result
1 Structural Catches wrong types, invalid enum
2 Rule Catches min/max/positive violations
3 Strip Removes 12 hallucinated metadata fields
$ moon run examples/mock/educational_agent

Output be like:

── Round 1 ──────────────────────────
  [lessons] Expected array (got: "not-an-array")
── Round 2 ──────────────────────────
  [title] String must contain at least 10 character(s)
  [lessons[0].duration_minutes] Value must be positive
── Round 3 ──────────────────────────
  ✅ VALIDATION PASSED (12 extra fields stripped)

multiple_schemas

Path: examples/multiple_schemas/README

The most comprehensive schema composition example. Outputs different representations based on CLI argument:

$ moon run examples/multiple_schemas -- ts       # TypeScript interface prompt
$ moon run examples/multiple_schemas -- json     # JSON Schema
$ moon run examples/multiple_schemas -- moonbit  # MoonBit struct code
$ moon run examples/multiple_schemas -- moon_zod # moon_zod builder code

Demonstrates .partial(), .omit(), .pick(), .extend_with(), .merge(), tuple, any/unknown, preprocess, transform, refine, union, intersection, literal, default, and more.

$ moon run examples/multiple_schemas -- ts

Output be like:

show only TypeScript Interface with Names

export interface User {
  name: string,  // [2-50 chars] — The user's display name, 2-50 characters
  age: number,  // [int, 0-150]
}

export type ProductMetadata = {
  description?: string,  // [max: 2000]
  images: string[],  // [max: 10 items, url] — Product image URLs
} | null

export interface Product {
  name: string,  // [min: 1, product name cannot be 'invalid'] — Product display name
  price: number,  // [positive] — Price in dollars
  currency?: string,  // [String must contain exactly 3 character(s)] — ISO 4217 currency code
  in_stock?: boolean,  // Whether the product is currently in stock
  metadata?: ProductMetadata,
}

type OrderStatus = "pending" | "shipped" | "delivered" | "cancelled"

export interface HomeAddress {
  type: "home",
  street: string,  // [min: 1]
  city: string,  // [min: 1]
}

export interface OfficeAddress {
  type: "office",
  company: string,  // [min: 1]
}

export type Address = HomeAddress | OfficeAddress

export type OrderId = {
  id: number,  // [int, positive]
} & {
  id: number,  // [int, max: 100]
}

export interface DateTime {
  created_at: string,  // [date-time] — The time the order was created
  updated_at: string,  // [date-time] — The last time the order was updated
}

export type OrderInfo = OrderId & DateTime

export interface ShippingInfo {
  address: Address,
  tracking_number?: string,  // Tracking number, available after shipment
  estimated_days?: number,  // [int, 1-30] — Estimated delivery days
  gift_wrap?: boolean,  // Whether to gift wrap the order
  special_instructions?: string,  // Any special delivery instructions
}

export type ReviewScore = number | null  // [int, positive] — Rating from 1 to 5

export type PreprocessTransformSchema = string | null

export type Tuple = [string, number, boolean] | null

export interface Order {
  user: User,
  product: Product,
  status: OrderStatus,  // The status of an order
  quantity?: number,  // [int, positive] — Number of items ordered
  address: Address,
  info: OrderInfo,
  shipping: ShippingInfo,
  review_score?: ReviewScore,  // [int, positive] — Rating from 1 to 5
  notes?: string,  // Optional order notes
  is_priority?: boolean,  // Whether this is a priority order
  coupon_code?: string,  // Optional coupon code
  preprocessed_field?: PreprocessTransformSchema,
  tuple_field?: Tuple,
}

real_llm_agent

Path: examples/real_llm_agent/README

The full Schema → Prompt → LLM → Parse closed-loop. Two modes:

  • Prompt mode: moon_zod generates TS interface prompt → LLM returns JSON → moon_zod validates + strips
  • Tool mode: OpenAI structured outputs + moon_zod as second-layer defense
# MoonBit prompt mode (TS interface style)
$ python3 examples/real_llm_agent/agent.py product --moon-prompt

# Classic mode (JSON Schema in prompt)
$ python3 examples/real_llm_agent/agent.py product

# Tool calling mode (OpenAI function calling)
$ python3 examples/real_llm_agent/agent.py product --mode tool
python3 examples/real_llm_agent/agent.py product --moon-prompt

Output be like:

  Fetching schema for 'product'...
  Schema loaded (8 fields)

  user prompt:
  Generate a product listing in JSON format for:
  "Quantum Computing Starter Kit"
  
  Expected type:
  {
    name: string,  // [3-100 chars]
    description: string,  // [10-500 chars]
    price: number,  // [positive]
    currency: "USD" | "EUR" | "GBP" | "JPY" | "CNY",
    category: "electronics" | "clothing" | "food" | "books" | "other",
    tags: string[],  // [min: 1]
    stock: number,  // [int, min: 0]
    metadata?: {
      brand: string,  // [min: 1]
      weight_kg: number,  // [positive]
    },
  }

── Round 1 ──────────────────────────────────

  Calling deepseek-ai/DeepSeek-V3.2...
  LLM output:
    {
        "name": "Quantum Computing Starter Kit",
        "description": "A comprehensive introduction to quantum computing with educational materials, simulation software, and theoretical guides. Perfect for beginners interested in quantum algorithms, superposition, and entanglement concepts.",
        "price": 189.99,
        "currency": "USD",
        "category": "electronics",
        "tags": ["quantum", "educational", "electronics", "simulation", "beginner"],
        "stock": 45,
        "metadata": {
            "brand": "QuantumLabs",
            "weight_kg": 2.5
        }
    }

  Validating with moon_zod (product)...

  ✅ VALIDATION PASSED  (Strip mode active)

  Clean data (hallucinations stripped):
    Object(
      {
        "name": String("Quantum Computing Starter Kit"),
        "description": String("A comprehensive introduction to quantum computing with educational materials, simulation software, and theoretical guides. Perfect forbeginners interested in quantum algorithms, superposition, and entanglement concepts."),
        "price": Number(189.99),
        "currency": String("USD"),
        "category": String("electronics"),
        "tags": Array(
          [
            String("quantum"),
            String("educational"),
            String("electronics"),
            String("simulation"),
            String("beginner"),
          ],
        ),
        "stock": Number(45),
        "metadata": Object({ "brand": String("QuantumLabs"), "weight_kg": Number(2.5) }),
      },
    )

  ✅ Self-correction loop completed in 1 round(s)
════════════════════════════════════════════════════════════
  Status: ✅ Success
  Rounds: 1
  Strip:  Extra fields removed by moon_zod default mode
════════════════════════════════════════════════════════════

Supports cases: product, movie, course_catalog (nested, triggers correction).


schema2json

Path: examples/schema2json/README

Exports a moon_zod schema as standard JSON Schema with full constraint annotations:

$ moon run examples/schema2json -- product schema

Output be like:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 3,
      "maxLength": 100
    },
    "description": {
      "type": "string",
      "minLength": 10,
      "maxLength": 500
    },
    "price": {
      "type": "number",
      "exclusiveMinimum": 0
    },
    "currency": {
      "type": "string",
      "enum": [
        "USD",
        "EUR",
        "GBP",
        "JPY",
        "CNY"
      ]
    },
    "category": {
      "type": "string",
      "enum": [
        "electronics",
        "clothing",
        "food",
        "books",
        "other"
      ]
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1
      }
    },
    "stock": {
      "type": "integer",
      "minimum": 0
    },
    "metadata": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "brand": {
              "type": "string",
              "minLength": 1
            },
            "weight_kg": {
              "type": "number",
              "exclusiveMinimum": 0
            }
          },
          "additionalProperties": false,
          "required": [
            "brand",
            "weight_kg"
          ]
        },
        {
          "type": "null"
        }
      ]
    }
  },
  "additionalProperties": false,
  "required": [
    "name",
    "description",
    "price",
    "currency",
    "category",
    "tags",
    "stock"
  ]
}

schema2prompt

Path: examples/schema2prompt/README

Converts a moon_zod schema into a TypeScript-interface prompt string with constraint comments:

$ moon run examples/schema2prompt -- product prompt

Output be like:

{
  name: string,  // [3-100 chars]
  description: string,  // [10-500 chars]
  price: number,  // [positive]
  currency: "USD" | "EUR" | "GBP" | "JPY" | "CNY",
  category: "electronics" | "clothing" | "food" | "books" | "other",
  tags: string[],  // [min: 1]
  stock: number,  // [int, min: 0]
  metadata?: {
    brand: string,  // [min: 1]
    weight_kg: number,  // [positive]
  },
}

validate CLI

Path: cmd/validate/README

Shell-based JSON validator. Infers schema from sample or reads JSON Schema, then validates JSON/JSONL input:

$ sh cmd/validate/cli.sh '{"name":"Alice"}' '{"name":"Bob"}'
Schema: let root = @moon_zod.object({ "name": @moon_zod.string() }).name("Root")
PASS
$ sh cmd/validate/cli.sh '{"name":"Alice"}' '{"age":30}'
Schema: let root = @moon_zod.object({ "name": @moon_zod.string() }).name("Root")
FAIL
  [name] Required (got: Null)

gen-struct CLI

Path: cmd/gen-struct/README

Converts JSON Schema into MoonBit struct definitions plus static Type::to_schema() functions:

$ sh cmd/gen-struct/cli.sh --from-json-schema '{"type":"object","properties":{"name":{"type":"string"},"age":{"type":"integer"}}}'
pub struct Root {
  name : String?
  age : Int64?  // int
} derive(ToJson, FromJson)

pub fn Root::to_schema() -> @moon_zod.Schema {
  let root = @moon_zod.object({ "name": @moon_zod.string().optional(), "age": @moon_zod.number().int().optional() }).name("Root")
  root
}

json2schema CLI

Path: cmd/json2schema/README

Infers a moon_zod schema from JSON, or reverse-imports from JSON Schema:

$ sh cmd/json2schema/cli.sh '{"name":"Alice","age":30}'
let root = @moon_zod.object({ "name": @moon_zod.string(), "age": @moon_zod.number().int() }).name("Root")

See Also