Tuesday, January 20, 2026

data schema: Pydantic, Zod, C#, Go, JSON schema, OpenAPI

Welcome to Pydantic - Pydantic Validation
Pydantic is the most widely used data validation library for Python.
JSON Schema - Pydantic Validation

Intro | Zod

TypeScript-first schema validation with static type inference


Basic Model Definition

Pydantic:

from pydantic import BaseModel, EmailStr, Field
from typing import List, Optional
from datetime import datetime
from uuid import UUID

class User(BaseModel):
    id: UUID
    email: EmailStr
    username: str = Field(min_length=3, max_length=20)
    age: int = Field(gt=0, le=120)
    created_at: datetime
    is_active: bool = True
    tags: List[str] = []
    metadata: Optional[dict] = None

Zod:

import { z } from 'zod';

const UserSchema = z.object({
  id: z.string().uuid(),
  email: z.string().email(),
  username: z.string().min(3).max(20),
  age: z.number().int().positive().max(120),
  created_at: z.string().datetime(),
  is_active: z.boolean().default(true),
  tags: z.array(z.string()).default([]),
  metadata: z.record(z.unknown()).nullable().optional()
});

type User = z.infer<typeof UserSchema>;

Sharing Schemas Between Python and TypeScript

Option 1: JSON Schema as Source of Truth

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "email": { "type": "string", "format": "email" },
    "age": { "type": "integer", "minimum": 0, "maximum": 120 }
  },
  "required": ["email", "age"]
}

Generate both:

  • Pydantic: datamodel-codegen
  • Zod: json-schema-to-zod

Option 2: OpenAPI Specification

components:
  schemas:
    User:
      type: object
      properties:
        email:
          type: string
          format: email
        age:
          type: integer
          minimum: 0
          maximum: 120

Generate from OpenAPI:

  • Pydantic: FastAPI auto-generates
  • Zod: Use openapi-zod-client



Google AI summary: 

Pydantic and Zod are language-specific libraries for data validation in Python and TypeScript/JavaScript, respectively, while JSON Schema is a language-agnostic, declarative standard for defining data structures. Pydantic and Zod can both generate and work with JSON Schema. 
JSON Schema
  • Purpose: A standardized, declarative language (using JSON format itself) for describing the structure, constraints, and data types of a JSON document. It is primarily for data validation and documentation.
  • Language Agnostic: It is not tied to any specific programming language. The same JSON Schema can be used to validate data in Python, JavaScript, Java, etc., using a compatible validator library in each language.
  • Interoperability: Excellent for defining API contracts and data exchange formats between different systems and services. It's the standard used in OpenAPI documentation.
  • Drawbacks: It is purely declarative and does not include runtime logic like data transformation or complex custom validation rules that can be expressed directly in code. 
Pydantic
  • Purpose: A Python-specific library for data validation, serialization, and deserialization using Python type hints. It provides runtime data validation, which is crucial for handling external data sources.
  • Language Specific: It is deeply integrated into the Python ecosystem and uses Python classes and type hints, making it very "Pythonic".
  • Features:
    • Runtime Validation: Validates data when a Pydantic model is instantiated.
    • Serialization/Deserialization: Converts Python objects to and from JSON or other formats.
    • JSON Schema Generation: Can automatically generate a JSON Schema from a Pydantic model, ensuring APIs are well-documented and consistent.
    • Integration: Widely used in frameworks like FastAPI and LangChain.
  • Drawbacks: Specific to Python; cannot be used directly in a TypeScript frontend, for example. 
Zod
  • Purpose: A TypeScript-first schema validation library for defining, validating, and transforming data. It works seamlessly with TypeScript's static type checking, inferring types from the schemas.
  • Language Specific: Primarily used in the TypeScript/JavaScript ecosystem (e.g., in Node.js backends or React frontends for form validation).
  • Features:
    • Runtime Validation: Validates data at runtime, which complements TypeScript's compile-time checks.
    • Data Transformation: Supports chained transformations, allowing data to be cleaned and normalized during the validation process.
    • TypeScript Inference: Generates TypeScript types from the Zod schema as the source of truth, minimizing code duplication.
    • JSON Schema Generation: Can generate JSON Schemas from Zod schemas.
  • Drawbacks: Specific to the TypeScript/JavaScript ecosystem; cannot be used directly in a Python backend. 
Summary of Differences
Feature JSON SchemaPydanticZod
LanguageLanguage-agnostic (declarative JSON)Python-specificTypeScript/JavaScript-specific
RoleDeclarative data structure definition and validation standardPython library for data validation, serialization, and modelingTS/JS library for schema validation, inference, and transformation
IntegrationUsed across all languages; the standard for APIsDeeply integrated into Python frameworks (e.g., FastAPI)Deeply integrated into TS/JS applications (e.g., form/API validation)
Schema GenerationN/A (is the schema format)Can generate JSON SchemaCan generate JSON Schema
Source of TruthThe schema file is the sourcePython code is the sourceTypeScript code is the source (TS types inferred)
In short: Use Pydantic if you're in a Python environment, Zod if you're in a TypeScript/JavaScript environment, and JSON Schema when you need a universal, language-agnostic contract for data exchange between different systems. Often, Pydantic and Zod are used to generate the JSON Schema needed for interoperability. 



In Go and C#, data validation and schema definition capabilities similar to Pydantic and Zod are provided through different libraries and language features, with a strong emphasis on static typing and compiler-time checks. 

Go (Golang) Equivalents
Go is a statically typed language, so much of the "validation" is handled by the type system at compile time. However, specific libraries exist to handle runtime validation, particularly when dealing with external data like JSON payloads. 
  • go-playground/validator: This is the most common and widely used library for Go validation. It uses struct tags to define validation rules (e.g., validate:"required,gte=10,lte=100"), which is a common pattern in Go for metadata. It focuses purely on validation and is highly performant.
  • Zod-inspired libraries: Several libraries mimic the fluent, chainable API of Zod for those who prefer that style:
    • zod-go (by aymaneallaoui) and Zog (by Oudwins) offer a similar API for readable validation code and handle complex, nested validations.
    • GoZod is another TypeScript Zod-inspired library focused on strongly-typed, zero-dependency data validation.
  • godantic: This library specifically aims to provide Pydantic-like functionality, including JSON schema generation and validation for Go structs, often used with LLM integrations or APIs like Gin. 
C# Equivalents
C# is also a statically typed, feature-rich language within the robust .NET ecosystem. 
  • Data Annotations: This is the built-in, standard way to apply validation rules in C# and the .NET framework, especially in ASP.NET Core MVC/API projects. You use attributes like [Required][StringLength(100, MinimumLength = 10)], and [Range(0, 100)] on model properties.
  • FluentValidation: This popular third-party library provides a fluent interface for building validation rules within separate validator classes, which helps decouple validation logic from the data models themselves.
  • Strong Typing and Serialization: The core C# type system and JSON serialization libraries (like System.Text.Json or Newtonsoft.Json) inherently handle basic type checking and required fields during deserialization, similar to Pydantic's core function of enforcing type hints at runtime.
  • Custom Libraries: While less common than in Go, some developers seek Zod-like runtime schema validation, though the strong C# type system often makes dedicated, external libraries less necessary than in dynamic languages like Python or JavaScript. 

No comments: