JSON Schema Data Types: A Complete Guide to Validation
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. |
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
emailfield must be a valid email address -
An
agefield 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:
-
String
-
Number and integer
-
Boolean
-
Null
-
Object
-
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
numberandintegerdifferently - 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": falseis enabled -
APIs often return metadata fields like
id,created_at, orlinks
How to fix
-
Remove
"additionalProperties": falseif 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
formatkeyword is optional in JSON Schema -
Not all validators enforce format checks
How to fix
-
Treat
formatas a readability aid, not a guarantee -
Combine
formatwithpatternwhen 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
-
requiredcontrols presence, not value -
typecontrols 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
-
itemsschema is missing or too permissive -
No constraints on item structure or type
How to fix
-
Always define
itemsexplicitly -
Add validation rules inside the
itemsschema -
Use
minItemsanduniqueItemswhere 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.