JSON Schema Data Types: A Complete Guide to Validation

JSON Schema Data Types: A Complete Guide to Validation

User Avatar

Quick reference

Question Answer
When should I use JSON Schema? Use JSON Schema to validate API requests and responses, enforce consistency across services, and clearly document data contracts.
Can I validate nested objects? Yes. Define schemas inside properties to support deeply nested objects.
How do I allow multiple types? Use an array. "type": ["string", "number"]allows either type.
What’s the difference between null and missing? null is an explicit value. Missing means the property is not present at all. Control these independently using required and nullable types.
Do all tools enforce format validation? No. Format validation is optional. Always test your validator and use pattern as a fallback when correctness matters.


Try Postman today →

If you’ve worked with APIs long enough, you’ve seen how small data mismatches cause outsized problems. A user registration endpoint receives a string instead of an integer. An array arrives empty when at least one item is required. A field quietly changes shape and breaks downstream consumers.

JSON Schema solves these problems by defining exactly what your API data should look like and validating it automatically. Instead of discovering issues in production, you catch them at the boundary.

This guide walks through all JSON Schema data types, explains how validation works in practice, and shows how to test schemas against real API responses in Postman.

What is JSON Schema?

JSON Schema is a language for describing and validating the structure of JSON data. It acts as a contract between API producers and consumers by specifying:

  • Which fields must be present

  • What data types they must contain

  • What constraints apply to their values

When you apply JSON Schema to an API, it becomes a validation layer. Incoming requests and outgoing responses are checked before your application logic runs. If data violates the contract, validation fails early with clear, actionable errors.

Examples of schema rules include:

  • An email field must be a valid email address

  • An age field must be an integer between 18 and 120

  • An array must contain at least one item

Schemas turn assumptions into enforceable rules.

Why use JSON Schema?

Catch errors early

Invalid data is rejected before it reaches your code or database.

Create clear contracts

Schemas describe your API in a format both humans and machines can understand.

Maintain consistency across services

When multiple teams use the same schema, the data shape stays predictable.

Reduce debugging and rework

Automated validation replaces manual checks and defensive coding.

These benefits compound as APIs grow, especially when responses are reused across frontend, backend, and automated consumers.

The six JSON Schema types

JSON Schema supports six core data types that map directly to the JSON data type itself:

  1. String

  2. Number and integer

  3. Boolean

  4. Null

  5. Object

  6. Array

Each type has its own validation rules.

String type

Strings represent text values such as names, emails, URLs, or identifiers:

{
  "type": "string"
}
</code

This accepts any string value, but production APIs usually require additional constraints.

Common string validation rules

Length constraints

Control string length with minLength and maxLength:

{
"type": "string",
"minLength": 3,
"maxLength": 50
}

This requires strings between 3 and 50 characters, which is useful for usernames, titles, or any field where you want to prevent empty values and excessively long input.

Pattern matching

Use pattern to match specific formats with regular expressions:

{
  "type": "string",
  "pattern": "^[A-Z]{2}[0-9]{6}$"
}

This enforces a strict format such as AB123456.

Format validation

The format keyword validates common string types:

{
  "type": "string",
  "format": "email"
}

Common formats include email, date, date-time, uri, uuid, hostname, and ipv4. Because format support varies by validator, treat it as a convenience, not a guarantee.

Real-world string example

User profile schema with string validation:

{
  "type": "object",
  "properties": {
    "username": {
      "type": "string",
      "minLength": 3,
      "maxLength": 20,
      "pattern": "^[a-zA-Z0-9_]+$"
    },
    "email": {
      "type": "string",
      "format": "email"
    },
    "bio": {
      "type": "string",
      "maxLength": 500
    }
  },
  "required": ["username", "email"]
}

Number and integer types

The number type accepts any numeric value, including decimals, while the integer type only accepts whole numbers.

{
  "type": "number"
}
{
  "type": "integer"
}

Use integer for quantities and counts. Use number for values like prices or measurements.

Numeric validation rules

Minimum and maximum

{
  "type": "number",
  "minimum": 0,
  "maximum": 100
}

Exclusive boundaries

{
  "type": "number",
  "exclusiveMinimum": 0,
  "exclusiveMaximum": 100
}

Specific increments

{
  "type": "integer",
  "multipleOf": 5
}

This only accepts numbers divisible by 5. For prices, multipleOf: 0.01 ensures at most two decimal places.

Real-world numeric example

Product pricing schema:

{
  "type": "object",
  "properties": {
    "price": {
      "type": "number",
      "minimum": 0,
      "exclusiveMinimum": true,
      "multipleOf": 0.01
    },
    "quantity": {
      "type": "integer",
      "minimum": 1,
      "maximum": 999
    },
    "discount_percent": {
      "type": "number",
      "minimum": 0,
      "maximum": 100
    }
  },
  "required": ["price", "quantity"]
}

Boolean type

The boolean type only accepts true or false.

{
  "type": "boolean"
}

123{ “type”: “boolean”}​

Use booleans for flags, toggles, or yes/no settings.

Real-world boolean example

User notification settings:

{
  "type": "object",
  "properties": {
    "email_notifications": {
      "type": "boolean",
      "default": true
    },
    "newsletter": {
      "type": "boolean"
    },
    "two_factor_auth": {
      "type": "boolean",
      "default": false
    }
  }
}

Null type

The null type represents an explicit empty value.

{
  "type": "null"
}
</code

Allowing null values

</code class="language-">{
  "type": ["string", "null"]
}

This accepts a string or null, which is useful for optional fields like middle names.

Real-world nullable example

{
  "type": "object",
  "properties": {
    "first_name": {
      "type": "string"
    },
    "middle_name": {
      "type": ["string", "null"]
    },
    "last_name": {
      "type": "string"
    }
  },
  "required": ["first_name", "last_name"]
}

Object type

Objects represent structured data using key-value pairs. Most API payloads are objects at the top level.

{
  "type": "object"
}

Object validation rules

Defining properties

{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer" }
  }
}

Required fields

{
  "required": ["name", "email"]
}

Restricting extra fields

{
  "additionalProperties": false
}

This enforces strict contracts but reduces flexibility.

Real-world object example
User registration schema:

{
  "type": "object",
  "properties": {
    "username": {
      "type": "string",
      "minLength": 3,
      "maxLength": 20
    },
    "email": {
      "type": "string",
      "format": "email"
    },
    "password": {
      "type": "string",
      "minLength": 8
    },
    "age": {
      "type": "integer",
      "minimum": 18
    }
  },
  "required": ["username", "email", "password"],
  "additionalProperties": false
}

Array type

Arrays are ordered lists that represent collections, such as product lists, user permissions, or search results. They can enforce uniform types (all strings) or allow mixed types.

{
  "type": "array"
}

Array validation rules

Item type

{
  "type": "array",
  "items": {
    "type": "string"
  }
}

Length constraints

{
  "type": "array",
  "minItems": 1,
  "maxItems": 10
}

Unique values

{
  "type": "array",
  "uniqueItems": true
}

Real-world array examples
Product tags with constraints:

{
  "type": "object",
  "properties": {
    "product_name": {
      "type": "string"
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 2,
        "maxLength": 20
      },
      "minItems": 1,
      "maxItems": 10,
      "uniqueItems": true
    }
  }
}

This ensures that products have 1-10 unique tags, each 2-20 characters in length.
Order items with object validation:

{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "product_id": { "type": "string" },
      "quantity": { "type": "integer", "minimum": 1 },
      "price": { "type": "number", "minimum": 0 }
    },
    "required": ["product_id", "quantity", "price"]
  },
  "minItems": 1
}

Testing JSON Schema validation in Postman

Defining a schema is only half the work. The real value comes from validating schemas against actual API responses.

In Postman, you can validate JSON Schema directly in tests.

Basic schema validation

Create a request in Postman and add this test script in the Tests tab:

pm.test("Response matches schema", function() {
    const schema = {
        type: "object",
        properties: {
            id: { type: "integer" },
            username: { type: "string" },
            email: { type: "string", format: "email" }
        },
        required: ["id", "username", "email"]
    };
    
    pm.response.to.have.jsonSchema(schema);
});

If the response violates the schema, the test fails with detailed errors.

Validating success and error responses

Test different status codes with different schemas:

pm.test("Schema validation", function() {
    const successSchema = {
        type: "object",
        properties: {
            status: { const: "success" },
            data: { type: "object" }
        },
        required: ["status", "data"]
    };
    
    const errorSchema = {
        type: "object",
        properties: {
            status: { const: "error" },
            message: { type: "string" }
        },
        required: ["status", "message"]
    };
    
    if (pm.response.code === 200) {
        pm.response.to.have.jsonSchema(successSchema);
    } else if (pm.response.code >= 400) {
        pm.response.to.have.jsonSchema(errorSchema);
    }
});

This approach keeps validation close to actual API behavior.

Common validation patterns

Enums

Restrict fields to predefined allowed values:

{
  "type": "string",
  "enum": ["pending", "processing", "completed", "cancelled"]
}

This only accepts those four status values. Enums are perfect for status fields, categories, or any field with fixed options.
Multiple allowed types

Allow fields to accept different types:

{
  "type": ["string", "number"]
}</code

This accepts either strings or numbers.

Conditional validation

Apply different rules based on field values:

{
  "type": "object",
  "properties": {
    "country": { "type": "string" },
    "postal_code": { "type": "string" }
  },
  "if": {
    "properties": { "country": { "const": "US" } }
  },
  "then": {
    "properties": {
      "postal_code": { "pattern": "^[0-9]{5}(-[0-9]{4})?$" }
    }
  }
}

This validates US ZIP codes with the 5-digit format while allowing flexible formats for other countries.

Troubleshooting common JSON Schema validation issues

Even well-written schemas can fail in unexpected ways. Most issues come from subtle mismatches between schema assumptions and real API behavior. These are the most common problems teams encounter and how to resolve them.

Schema rejects data that looks valid

Problem
Validation fails even though the response appears correct.

Common causes

  • Using "type": "number" when the value is actually an integer or vice versa
  • Expecting a string but receiving a numeric ID
  • Overly strict patternrules

How to fix

  • Confirm the actual response type, not the intended type
  • Remember that JSON Schema treats number and integer differently
  • Validate against real responses, not sample payloads

In Postman, inspect the response body directly and compare it to the schema used in your test. Small mismatches are easier to spot when validation runs against live data.

Extra fields cause validation failures

ProblemValidation fails because the response contains unexpected properties.

Why it happens

  • "additionalProperties": false is enabled

  • APIs often return metadata fields like id, created_at, or links

How to fix

  • Remove "additionalProperties": false if flexibility is required

  • Explicitly define all expected fields, including metadata

  • Use strict schemas only where backward compatibility is controlled

Strict validation is useful for internal contracts, but it can be fragile for public or evolving APIs.

Format validation does not work as expected

Problem

Invalid emails, dates, or URLs still pass validation.

Why it happens

  • The format keyword is optional in JSON Schema

  • Not all validators enforce format checks

How to fix

  • Treat format as a readability aid, not a guarantee

  • Combine format with pattern when correctness matters

Example:

{
"type": "string",
"format": "email",
"pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"
}

Always test your schema using the same validator you rely on in automation.

Null and missing properties behave the same

ProblemSchemas accept or reject null values unexpectedly.

Why it happens

  • required controls presence, not value

  • type controls allowed values, not existence

How to fix

  • Use "required" to enforce that a property exists

  • Use "type": ["string", "null"] to allow explicit null values

  • Remember that these are independent rules

A required field can still be null unless the schema explicitly prevents it.

Arrays validate but contain invalid items

ProblemThe array itself passes validation, but individual items are incorrect.

Why it happens

  • items schema is missing or too permissive

  • No constraints on item structure or type

How to fix

  • Always define items explicitly

  • Add validation rules inside the items schema

  • Use minItems and uniqueItems where applicable

Example:

{
  "type": "array",
  "items": {
    "type": "string",
    "minLength": 2
  },
  "minItems": 1
}

Validation passes locally but fails in CI

Problem

Schemas behave differently in automation than during manual testing.

Why it happens

  • Different validators or schema draft versions

  • Inconsistent test data across environments

How to fix

  • Use the same schema and validator everywhere

  • Validate against real API responses in Postman before running in CI

  • Version schemas alongside API changes

Consistency matters more than strictness when schemas are part of automated workflows.

Best practices

  • Start with the required fields to define your core contract.

  • Use schemas as executable contracts, not just documentation.

  • Validate schemas against real responses in Postman.

  • Version schemas to avoid breaking consumers.

  • Share schemas across teams so that everyone works from the same set of rules.

When schemas are tested continuously, they become a safety net that scales with your API program.

What do you think about this topic? Tell us in a comment below.

Comment

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.