// blog/developer/
Back to Blog
Developer · May 26, 2026 · 9 min read · Updated May 22, 2026

JSON Schema Validation: Catch API Bugs Before Production

JSON Schema Validation: Catch API Bugs Before Production

You build an API endpoint. It accepts a JSON body with a user's name, email, and age. You write the handler, connect it to the database, and deploy. Everything works. Then three weeks later, the frontend team sends a request where age is a string instead of a number, email is missing entirely, and there is an extra field called "username" that your database does not have a column for. Your handler crashes, the database throws a type error, and you spend an hour tracking down what went wrong.

JSON Schema validation prevents this entire category of bugs. A JSON Schema is a document that describes the structure, types, and constraints of a JSON object. When a request comes in, you validate it against the schema before your handler ever touches the data. If the payload does not match, the request gets rejected with a clear error message. Your handler only receives data that conforms to the shape you expect.

The JSON Validator lets you paste any JSON and validate its syntax instantly. For checking whether your JSON matches a specific schema, you need a schema validator library in your language of choice.

* * *

What Is JSON Schema and Why Should You Care?

JSON Schema is a vocabulary for annotating and validating JSON documents. It is defined by a specification (currently Draft 2020-12) and supported by libraries in every major programming language.

At its simplest, a JSON Schema defines the expected properties, their types, and which ones are required:

`json { "type": "object", "properties": { "name": { "type": "string", "minLength": 1 }, "email": { "type": "string", "format": "email" }, "age": { "type": "integer", "minimum": 0 } }, "required": ["name", "email"] } `

This schema tells you everything about the expected payload. Name must be a non-empty string. Email must be a string in email format. Age must be a non-negative integer. Name and email are required, age is optional.

The real value is that this schema serves three purposes at once: it validates incoming data, it documents the API contract, and it generates TypeScript types or OpenAPI specs. Write the schema once, and it pays dividends across your entire stack.

Use the JSON Formatter to clean up and indent your schemas for readability. Well-formatted schemas are much easier to review and maintain.

Code editor showing JSON data structure
Code editor showing JSON data structure
* * *

Validating API Requests: Server-Side and Client-Side

Validation should happen on the server, period. Client-side validation is a user experience improvement, not a security measure. Anyone can bypass your frontend and send raw HTTP requests directly to your API.

The typical validation flow for an API endpoint:

  1. Request arrives at your endpoint
  2. Parse the JSON body (reject if not valid JSON)
  3. Validate the parsed object against your JSON Schema
  4. If validation fails, return a 400 response with the specific errors
  5. If validation passes, proceed with your business logic

Popular validation libraries by language:

JavaScript/TypeScript: Ajv is the de facto standard. It compiles schemas into optimized validation functions and is extremely fast. Zod is an alternative that defines schemas in TypeScript code rather than JSON.

Python: jsonschema is the most widely used library. Pydantic takes a different approach by defining schemas as Python classes, which is more Pythonic.

Go: gojsonschema handles validation. For a more Go-native approach, go-playground/validator uses struct tags.

Java: everit-org/json-schema handles all draft versions.

The validation error messages matter as much as the validation itself. A message like "validation failed" tells the caller nothing. A message like "age must be an integer, received string '25'" tells them exactly what to fix.

Key takeaway

Validation should happen on the server, period.

* * *

Advanced Schema Patterns for Real APIs

Simple type checking is just the start. JSON Schema supports patterns that handle the messy reality of API data:

Conditional fields: Some fields should only be present when another field has a specific value. Use if/then/else in the schema. For example, if accountType is "business," then companyName is required.

Polymorphic payloads: When the same endpoint accepts different shapes (a webhook that handles multiple event types), use oneOf or discriminator to validate against the correct sub-schema based on a type field.

String patterns: Email, URL, date-time, and UUID formats are built in. For custom patterns (phone numbers, postal codes, product SKUs), use the pattern keyword with a regex.

Array constraints: Validate not just that a field is an array, but that it has at least one item (minItems: 1), that all items match a schema (items: { ... }), or that items are unique (uniqueItems: true).

Nested objects: Schemas compose naturally. Define a reusable Address schema and reference it from Order, User, and Warehouse schemas using $ref. This keeps your schemas DRY and maintainable.

Additional properties: By default, JSON Schema allows extra fields not defined in properties. Set additionalProperties: false to reject payloads with unexpected fields. This catches typos ("emial" instead of "email") and prevents accidental data leakage.

* * *

JSON Schema and OpenAPI: The Connection

OpenAPI (formerly Swagger) is the most widely used standard for documenting REST APIs. The schema definitions inside an OpenAPI document are JSON Schemas. If you already have JSON Schemas for your request and response payloads, you have most of what you need for a full OpenAPI spec.

The practical benefit is that your validation schemas and your API documentation stay in sync. When you add a new required field to your schema, the documentation automatically reflects it. When you change a field's type, the generated client libraries pick up the change.

Tools like openapi-generator can produce client SDKs in dozens of languages from your OpenAPI spec. If your spec is backed by accurate JSON Schemas, the generated clients have correct types, which saves frontend and mobile teams from guessing what shape your API responses return.

For APIs that use YAML for their OpenAPI specs, the YAML Validator catches syntax issues before they break your documentation pipeline. YAML indentation errors are notoriously hard to spot by eye, and a single misplaced space can change the meaning of a key.

Developer debugging API responses on dual monitors
Developer debugging API responses on dual monitors
* * *

Testing with JSON Schema: Contract Tests

Contract testing uses schemas to verify that your API endpoints return what they promise. Unlike integration tests that check specific values, contract tests check the shape of the response. This catches a different class of bugs.

A contract test validates:

  • The response status code matches expectations
  • The response body conforms to the documented JSON Schema
  • Required fields are present
  • Field types match (a price should never come back as a string)
  • Enum values are within the allowed set

The advantage of contract tests over snapshot tests is flexibility. Snapshot tests break when any value changes, even if the shape is correct. Contract tests only break when the structure changes, which is what actually matters for API consumers.

Write contract tests for every public endpoint. Run them in CI. When a contract test fails, it means you changed your API's shape, which is a breaking change that needs a version bump and client notification. Catching that in CI rather than production saves relationships with your API consumers.

Combine contract tests with the JSON Validator during development to quickly verify that your test fixtures and mock data are valid JSON before running your test suite.

* * *

Performance Considerations for Schema Validation

Schema validation adds overhead to every request. For most APIs, this overhead is negligible. Ajv, the fastest JavaScript validator, validates simple schemas in under 1 microsecond. Even complex schemas with nested objects, arrays, and conditional logic typically validate in under 100 microseconds.

There are situations where validation performance matters:

High-throughput APIs: If you process millions of requests per second, compile your schemas at startup rather than on every request. Ajv supports schema compilation, which converts a JSON Schema into an optimized JavaScript function. The first call is slow; subsequent calls are extremely fast.

Large payloads: Validating a 10MB JSON array with 100,000 items takes measurably longer than validating a small object. Consider validating only the top-level structure synchronously and validating array items in batches if needed.

Recursive schemas: Schemas that reference themselves (tree structures, nested comments) can cause performance issues with very deep nesting. Set maxDepth limits to prevent pathological inputs from consuming excessive CPU.

For the vast majority of web APIs handling typical request volumes, just add validation and do not worry about the performance. The time saved debugging bad data in production is worth far more than the microseconds spent validating each request.

Key takeaway

Schema validation adds overhead to every request.

* * *

FAQ

What is the difference between JSON validation and JSON Schema validation?

JSON validation checks whether a string is valid JSON (correct syntax, matching brackets, properly quoted strings). JSON Schema validation goes further: it checks whether a valid JSON document matches a specific structure (correct field names, types, required fields, value constraints). You need the first before you can do the second.

Should I use JSON Schema or Zod for TypeScript projects?

Both are valid choices. JSON Schema is language-agnostic, making it ideal if your API is consumed by clients in multiple languages. Zod is TypeScript-native, which means you get type inference for free and the syntax feels more natural in a TypeScript codebase. If you only work in TypeScript, Zod is often the simpler choice.

Can JSON Schema validate nested objects?

Yes. JSON Schema supports nested objects, arrays of objects, and deeply nested structures. Use the properties keyword for each level of nesting, or use $ref to reference reusable sub-schemas. There is no depth limit imposed by the specification.

How do I handle optional fields with default values?

JSON Schema has a default keyword, but it is only a documentation hint. Most validators do not insert default values automatically. If you need defaults applied, handle that in your application code after validation passes, or use a library like Ajv with the useDefaults option enabled.