{}JSONLint.app

Paste your schema on the left and data on the right to validate:

Loading...
Loading...

What is JSON Schema?

JSON Schema is a declarative language for defining the structure of JSON data. Think of it as TypeScript types, but for JSON—you define what properties exist, their types, and any constraints. Then you can validate any JSON document against that schema.

When to Use Schema Validation

  • API request validation — Reject malformed requests before they hit your business logic
  • Configuration files — Catch typos in config before deployment
  • Form data — Validate user input on both client and server
  • Data pipelines — Ensure incoming data matches expected format
  • API documentation — Schemas serve as living documentation

Quick Reference

Basic Types

{ "type": "string" }
{ "type": "number" }
{ "type": "integer" }
{ "type": "boolean" }
{ "type": "null" }
{ "type": "array" }
{ "type": "object" }

String Constraints

{
  "type": "string",
  "minLength": 1,
  "maxLength": 100,
  "pattern": "^[a-z]+$",
  "format": "email"  // or: uri, date-time, uuid
}

Number Constraints

{
  "type": "number",
  "minimum": 0,
  "maximum": 100,
  "exclusiveMinimum": 0,
  "multipleOf": 0.01
}

Object with Required Properties

{
  "type": "object",
  "properties": {
    "id": { "type": "integer" },
    "name": { "type": "string" },
    "email": { "type": "string", "format": "email" }
  },
  "required": ["id", "name"],
  "additionalProperties": false
}

Array Validation

{
  "type": "array",
  "items": { "type": "string" },
  "minItems": 1,
  "maxItems": 10,
  "uniqueItems": true
}

Complete Example

Here's a schema for a user profile API response:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": { 
      "type": "integer",
      "minimum": 1
    },
    "username": { 
      "type": "string",
      "minLength": 3,
      "maxLength": 20,
      "pattern": "^[a-zA-Z0-9_]+$"
    },
    "email": { 
      "type": "string", 
      "format": "email" 
    },
    "role": { 
      "type": "string",
      "enum": ["admin", "user", "guest"]
    },
    "profile": {
      "type": "object",
      "properties": {
        "bio": { "type": "string", "maxLength": 500 },
        "avatar": { "type": "string", "format": "uri" }
      }
    },
    "createdAt": { 
      "type": "string", 
      "format": "date-time" 
    }
  },
  "required": ["id", "username", "email", "role"],
  "additionalProperties": false
}

Understanding Validation Errors

When validation fails, you'll see errors like:

  • must have required property 'name' — A required field is missing
  • must be string — Wrong type (e.g., number instead of string)
  • must match format "email" — String doesn't match the format
  • must NOT have additional properties — Unknown field whenadditionalProperties: false
  • must be >= 0 — Number violates minimum constraint

Pro Tips

  • 💡 Start strict — Use "additionalProperties": false to catch typos in property names. You can always loosen later.
  • 💡 Use enums for known values — Instead of just string, use "enum": ["active", "inactive"] when you know the valid values.
  • 💡 Add descriptions — Include "description" fields for documentation that travels with your schema.
  • 💡 Test edge cases — Validate with empty objects, null values, and boundary numbers to ensure your schema handles them correctly.

Supported Draft Version

This validator uses Ajv and supports JSON Schema draft-07 by default. Most draft-04 and draft-06 schemas will also work.

Related Tools

Learn More

Common Mistakes & Pro Tips

  • Declare the right draft in $schemaAJV validates against a specific draft, and keywords behave differently between them. Set "$schema" to e.g. "http://json-schema.org/draft-07/schema#" or "https://json-schema.org/draft/2020-12/schema" so you get the semantics you expect; in 2020-12, for instance, array tuples use "prefixItems" instead of an array-valued "items".
  • "required" is separate from "properties"Listing a field under "properties" only describes its shape if present, it does not make it mandatory. To require a field you must add its name to the "required" array on the same object level. A common bug is defining a property but forgetting to require it, so a document missing it still passes.
  • additionalProperties: false is strictSetting "additionalProperties": false rejects any key not explicitly named in "properties" (and "patternProperties"). It does not see properties inherited through "$ref", "allOf", or "oneOf", so combining it with composition often rejects valid data. Use it deliberately, and prefer "unevaluatedProperties" (2020-12) when composing schemas.
  • "format" is annotation-only by defaultKeywords like "email", "date-time", or "uri" do not fail validation unless format assertion is enabled. In AJV you must add the ajv-formats package and turn assertions on; otherwise a malformed email passes. Do not rely on "format" alone for input validation.
  • Numbers, integers, and type coercion"type": "integer" rejects 1.5 but accepts 1.0 because JSON has one number type; "type": "number" accepts both. AJV does not coerce strings to numbers unless coercion is explicitly enabled, so "42" fails an integer schema. Use "multipleOf", "minimum", and "exclusiveMinimum" for ranges.

Frequently Asked Questions

Which JSON Schema drafts are supported?

This validator uses AJV, which supports draft-07, draft 2019-09, and draft 2020-12 out of the box, plus draft-04/06 with configuration. The active dialect is chosen from the "$schema" keyword in your schema. If you omit "$schema", a default draft is assumed, so declaring it explicitly avoids surprises with keywords that changed between drafts.

Why does my document pass when a field is missing?

By default, every property is optional. A schema only enforces presence for fields listed in the "required" array. Add the field name to "required" at the correct object level; defining it under "properties" alone just constrains its value when it happens to be present.

How do I forbid unexpected fields?

Add "additionalProperties": false to the object schema so any key not named in "properties" or matched by "patternProperties" is rejected. Be careful when using "allOf"/"oneOf"/"$ref", since additionalProperties cannot see properties from those subschemas; in draft 2020-12 use "unevaluatedProperties": false instead to play well with composition.

Why isn't my "format": "email" rejecting bad emails?

In JSON Schema, "format" is an annotation by default and does not assert validity unless the validator is configured to enforce it. Enable format assertions (AJV does this via the ajv-formats plugin) to make formats like email, date-time, and uri actually fail invalid values. Without that, format is purely descriptive.

Can I reference other schemas with $ref?

Yes. "$ref" resolves pointers within the same schema document (for example "#/$defs/Address") and can target named definitions under "$defs" (or "definitions" in older drafts). External URL references require the target schema to be available to the validator; for fully client-side use, keep all definitions inside one schema document.

Is my data uploaded anywhere when I validate?

No. Validation runs entirely in your browser using AJV compiled to JavaScript. Both the schema and the document stay in memory on your device and are never sent to a server, which makes it safe to validate confidential or proprietary payloads.

How do I read the validation errors?

Each error reports an "instancePath" pointing to the location in your data (a JSON Pointer like /items/0/price) and a "schemaPath" pointing to the failing keyword in the schema. The "keyword" and "message" tell you which constraint failed. For "oneOf"/"anyOf" failures, inspect the nested errors, since the top-level message only says that no branch matched.