JSON Schema is itself a JSON document. It describes the expected shape of another JSON document. Think of it as a set of rules written in JSON format.
Let us say your API returns a user object like this:
{
"id": 1,
"name": "Rahul Sharma",
"email": "rahul@example.com",
"isActive": true
}Here is the JSON Schema that validates this response:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "User",
"description": "A user object from the API",
"type": "object",
"required": ["id", "name", "email", "isActive"],
"properties": {
"id": {
"type": "integer",
"minimum": 1
},
"name": {
"type": "string",
"minLength": 1
},
"email": {
"type": "string",
"format": "email"
},
"isActive": {
"type": "boolean"
}
},
"additionalProperties": false
}| Keyword | Purpose | Example |
|---|---|---|
| $schema | Declares which draft of JSON Schema you are using | "http://json-schema.org/draft-07/schema#" |
| title | Human-readable name for the schema | "User" |
| description | What this schema describes | "A user object from the API" |
| type | The data type of the root element | "object", "array", "string", "number", "integer", "boolean" |
| required | Array of field names that MUST be present | ["id", "name", "email"] |
| properties | Defines rules for each field inside the object | See individual field schemas |
| additionalProperties | Allow or reject fields not listed in properties | false = strict, true = permissive |
This is the most important keyword for QA. If a field is in the "required" array and the response does not have it — validation fails. If a field is NOT in "required," it is optional. The response can have it or not — both are valid.
{
"type": "object",
"required": ["id", "name"],
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"nickname": { "type": "string" }
}
}
// VALID: { "id": 1, "name": "Rahul" } ← nickname is optional
// VALID: { "id": 1, "name": "Rahul", "nickname": "R" }
// INVALID: { "id": 1 } ← name is missing
// INVALID: { "name": "Rahul" } ← id is missingThis controls whether the response can have fields you did not define. Set it to false for strict validation — if the API sneaks in an extra field, your test catches it.
// With "additionalProperties": false
{
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" }
},
"additionalProperties": false
}
// VALID: { "id": 1, "name": "Rahul" }
// INVALID: { "id": 1, "name": "Rahul", "age": 25 } ← "age" not defined in propertiesSetting "additionalProperties": false is great for catching unexpected changes. But it will also break your tests when the API team intentionally adds new fields. Discuss with your team: strict or permissive? For contract testing, strict is usually better.
When you have a nested object that appears in multiple schemas, you can define it once and reference it using $ref. This is like creating a reusable component.
{
"type": "object",
"required": ["id", "name", "address"],
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"address": { "$ref": "#/definitions/Address" }
},
"definitions": {
"Address": {
"type": "object",
"required": ["street", "city", "zipcode"],
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"zipcode": { "type": "string", "pattern": "^[0-9]{6}$" }
}
}
}
}Use $ref for objects that repeat across multiple schemas — like address, pagination metadata, or error response format. Define them once in "definitions" and reference everywhere. Keeps your schemas DRY.
Q: What are the key components of a JSON Schema?
A: A JSON Schema has: (1) $schema — declares the draft version, (2) type — the root data type (object, array, etc.), (3) properties — defines rules for each field including their types and constraints, (4) required — array of field names that must exist, (5) additionalProperties — controls whether extra fields are allowed, and (6) $ref and definitions — for reusing sub-schemas. The most important for QA are "required" (catches missing fields) and "type" (catches wrong data types).
Key Point: A JSON Schema uses type, properties, required, and additionalProperties to define the expected structure. $ref enables reuse of common sub-schemas.