JSON Schema type Keyword: All Data Types Explained
Last updated:
The type keyword is the foundation of every JSON Schema — it specifies which of the 7 JSON data types a value must belong to. Without it, any JSON value passes validation. With it, you get immediate, fast rejection of values in the wrong category before any other keyword is evaluated. This guide covers all 7 types, the integer/number distinction, type arrays for nullable fields, and a reference table mapping JSON values to their schema types.
The 7 JSON Schema Types
JSON Schema Draft 2020-12 defines 7 primitive types. These correspond to the value types in the JSON specification (RFC 8259) — string, number, object, array, boolean, and null — plus integer, which JSON Schema adds as a constrained subtype of number.
| Type name | Example values | Rejected by this type |
|---|---|---|
string | "hello", "", "2026-05-19" | 42, true, null, [], {} |
number | 42, 3.14, -7, 1e10 | "42", true, null, [], {} |
integer | 42, -7, 0, 1000000 | 3.14, "42", true, null, [], {} |
boolean | true, false | 1, 0, "true", null, [], {} |
array | [], [1, 2, 3], ["a", "b"] | "array", {}, null, true, 42 |
object | {}, {"a": 1} | [], "object", null, true, 42 |
null | null | "null", 0, false, [], {} |
Every JSON value belongs to exactly one of these 7 categories. JSON Schema validation checks category membership first — if the value is the wrong type, all other keywords (minLength, minimum, properties) are skipped.
// Basic type usage
{ "type": "string" } // ✅ "hello", ❌ 42
{ "type": "number" } // ✅ 3.14, ✅ 42, ❌ "42"
{ "type": "integer" } // ✅ 42, ❌ 3.14
{ "type": "boolean" } // ✅ true, ✅ false, ❌ 1
{ "type": "array" } // ✅ [1, 2], ❌ {}
{ "type": "object" } // ✅ {"a": 1}, ❌ [1, 2]
{ "type": "null" } // ✅ null, ❌ false
// No type keyword — any value passes
{} // ✅ "hello", ✅ 42, ✅ null, ✅ [], ✅ {}string Type
The string type accepts any sequence of Unicode characters enclosed in double quotes in JSON. In JSON Schema, type: "string" by itself accepts strings of any length including the empty string. Pair it with validation keywords to constrain the string further.
// String with length and pattern constraints
{
"type": "string",
"minLength": 1, // reject empty string
"maxLength": 100, // reject long strings
"pattern": "^[a-z]+$" // only lowercase ASCII letters
}
// String with format (requires ajv-formats to enforce)
{
"type": "string",
"format": "email" // date-time, uri, uuid, ipv4, hostname, etc.
}
// String with fixed set of allowed values
{
"type": "string",
"enum": ["draft", "published", "archived"]
}
// Nullable string (type array)
{
"type": ["string", "null"]
}
// Valid strings:
// "hello" ✅ — plain string
// "" ✅ — empty string (unless minLength > 0)
// "2026-05-19T10:30:00Z" ✅ — ISO timestamp as string
// Invalid for type: "string":
// 42 ❌ — number
// true ❌ — boolean
// null ❌ — null (use ["string", "null"] to allow)number and integer Types
number and integer are JSON Schema's two numeric types. number accepts any JSON numeric value — integers and decimals. integer accepts only values with a zero fractional part (42, -7, 0) and rejects decimals (3.14, -0.5). In practice, 42.0 passes integer because its fractional part is zero.
// number: accepts integers and decimals
{ "type": "number", "minimum": 0, "maximum": 1 }
// ✅ 0, ✅ 0.5, ✅ 1, ❌ -0.1, ❌ 1.1
// integer: rejects decimals
{ "type": "integer", "minimum": 1, "maximum": 100 }
// ✅ 1, ✅ 50, ✅ 100, ❌ 1.5, ❌ "50"
// Number-specific validation keywords
{
"type": "number",
"minimum": 0, // value >= 0
"exclusiveMinimum": 0, // value > 0 (Draft 2019+)
"maximum": 100, // value <= 100
"exclusiveMaximum": 100,// value < 100
"multipleOf": 0.01 // two decimal places (e.g. money)
}
// Integer-specific examples
{
"type": "integer",
"minimum": 1,
"maximum": 65535 // port number range
}
{
"type": "integer",
"minimum": 0,
"multipleOf": 1 // redundant but explicit
}
// When to use each:
// number → price (9.99), latitude (51.5), percentage (0.75)
// integer → count (5), page (2), port (8080), year (2026)The multipleOf keyword works with both number and integer. For money amounts, multipleOf: 0.01 with type: "number" rejects values with more than 2 decimal places — though for financial data, storing amounts as integer cents is more reliable.
boolean, array, and object Types
These three types cover the remaining structural JSON value types. Each is strict: 1 and 0 are not booleans; {} is not an array.
// boolean — only true or false
{ "type": "boolean" }
// ✅ true, ✅ false, ❌ 1, ❌ 0, ❌ "true", ❌ null
// array — ordered list, constrain with items / prefixItems
{
"type": "array",
"items": { "type": "string" }, // all elements must be strings
"minItems": 1,
"maxItems": 10,
"uniqueItems": true
}
// ✅ ["a", "b", "c"], ❌ {}, ❌ "array", ❌ [1, 2] (number ≠ string)
// array tuple (Draft 2020-12 prefixItems)
{
"type": "array",
"prefixItems": [
{ "type": "string" }, // index 0 must be string
{ "type": "number" } // index 1 must be number
],
"items": false // no additional items allowed
}
// ✅ ["alice", 42], ❌ ["alice", 42, "extra"]
// object — key-value pairs, constrain with properties / required
{
"type": "object",
"properties": {
"id": { "type": "string" },
"score": { "type": "number" }
},
"required": ["id"],
"additionalProperties": false
}
// ✅ {"id": "abc", "score": 9.5}
// ✅ {"id": "abc"} — score is optional
// ❌ {"id": "abc", "x": 1} — additionalProperties blocks unknown keys
// ❌ [] — array is not an objectnull and Nullable Fields
In JSON Schema, null is a standalone type. Only the JSON literal null passes {"type": "null"}. The values false, 0, "", and [] are falsy in JavaScript but are not null in JSON Schema.
// type: "null" — only the literal null passes
{ "type": "null" }
// ✅ null, ❌ false, ❌ 0, ❌ "", ❌ [], ❌ {}
// Standalone null type is rarely used alone.
// The practical use is in a type array: the nullable pattern.
// Nullable string — accepts "hello" or null
{ "type": ["string", "null"] }
// Nullable number — accepts 3.14 or null
{ "type": ["number", "null"] }
// Nullable object — accepts an object or null (e.g. an optional sub-resource)
{ "type": ["object", "null"] }
// Full schema: optional nullable field
{
"type": "object",
"properties": {
"name": { "type": "string" },
"deletedAt": { "type": ["string", "null"], "format": "date-time" }
},
"required": ["name"]
// deletedAt is optional (not in required) AND nullable (type includes null)
// deletedAt absent → valid
// deletedAt: null → valid
// deletedAt: "2026-05-19T10:00:00Z" → valid
}
// OpenAPI 3.0 used non-standard "nullable: true" — now deprecated in 3.1
// OpenAPI 3.0: { "type": "string", "nullable": true }
// OpenAPI 3.1: { "type": ["string", "null"] } ← use thisType Arrays: Multiple Allowed Types
The type keyword accepts either a single type name string or an array of type name strings. When an array is provided, the value must match at least one of the listed types.
// Accept string or number
{ "type": ["string", "number"] }
// ✅ "hello", ✅ 42, ✅ 3.14, ❌ null, ❌ true, ❌ {}
// Accept string, number, or null
{ "type": ["string", "number", "null"] }
// ✅ "hello", ✅ 42, ✅ null, ❌ true, ❌ {}
// Accept any type except null (list all 6 others)
{ "type": ["string", "number", "integer", "boolean", "array", "object"] }
// Type array vs oneOf — important difference:
// Type array only restricts primitive type — no per-type constraints
// WRONG if you need per-type constraints:
{ "type": ["string", "null"], "minLength": 1 }
// minLength applies even when value is null (but null has no length so Ajv
// skips it — still, behavior is implementation-defined)
// CORRECT for per-type constraints + nullable:
{
"oneOf": [
{ "type": "string", "minLength": 1, "maxLength": 100 },
{ "type": "null" }
]
}
// Ajv example: type array validation
// import Ajv from 'ajv'
// const ajv = new Ajv()
// const validate = ajv.compile({ type: ['string', 'null'] })
// validate('hello') // true
// validate(null) // true
// validate(42) // false — errors: [{ message: 'must be string,null' }]JSON-to-Schema Type Mapping Table
This table maps actual JSON values to their JSON Schema type, JavaScript typeof result, and TypeScript type. Use it as a quick reference when writing schemas for real API payloads.
| JSON value example | JSON Schema type | JavaScript typeof | TypeScript type |
|---|---|---|---|
"hello" | string | "string" | string |
"" | string | "string" | string |
42 | number and integer | "number" | number |
3.14 | number only | "number" | number |
true | boolean | "boolean" | boolean |
false | boolean | "boolean" | boolean |
[1, 2, 3] | array | "object" * | Array<number> |
{"a": 1} | object | "object" | Record<string, unknown> |
null | null | "object" * | null |
* JavaScript typeof quirk: arrays and null both return "object" in JavaScript but are distinct types in JSON Schema.
JSON Schema type vs JavaScript typeof vs TypeScript type
| JSON Schema type | JavaScript typeof result | TypeScript equivalent | Note |
|---|---|---|---|
string | "string" | string | Exact match |
number | "number" | number | Includes integers |
integer | "number" | number | No typeof distinction |
boolean | "boolean" | boolean | Exact match |
array | "object" | Array<T> / T[] | Use Array.isArray() |
object | "object" | Record<string, T> / interface | Excludes arrays and null |
null | "object" | null | Historic JS bug |
The key difference: JSON Schema's type distinguishes array, object, and null as separate types. JavaScript's typeof operator returns "object" for all three — a historic quirk. JSON Schema validators use internal type detection (equivalent to Array.isArray() and value === null checks) to make these distinctions correctly.
Definitions
- type keyword
- A JSON Schema keyword whose value is one of the 7 type name strings or an array of them. It restricts which category of JSON value is considered valid. A schema with no
typekeyword accepts any JSON value. Whentypeis present, values not matching the specified type(s) fail validation immediately without evaluating any other keywords. - integer
- A JSON Schema type name — not a separate JSON primitive. JSON itself has only one numeric type (number). JSON Schema defines
integeras a number value with a zero fractional part. The values 42, -7, and 0 are integers; 3.14 and -0.5 are not. The value 42.0 is an integer because its fractional part is zero. In Ajv, integer validation usesvalue % 1 === 0. - null
- A JSON primitive type representing the intentional absence of a value. In JSON Schema,
nullis one of the 7 valid type names. Only the JSON literalnullpasses{"type": "null"}. It is distinct from JavaScript'sundefined(which cannot appear in valid JSON), the empty string"", the number0, and the booleanfalse. Use{"type": ["string", "null"]}to allow a field to be either a string or null. - type array
- A JSON Schema feature where the
typekeyword's value is an array of type name strings instead of a single string. A value is valid if it matches any type in the array. The most common use is the nullable pattern:{"type": ["string", "null"]}. Type arrays perform only primitive type checking — they do not allow per-type constraints. For per-type constraints alongside multiple types, useoneOforanyOfinstead. - coercion
- Automatic conversion of a value from one type to another during validation. JSON Schema specification does not define or endorse coercion — validation is strictly type-based. Some validators like Ajv offer a
coerceTypesoption that converts string"42"to number42, or string"true"to booleantrue, before validating. This is useful for HTTP query parameters (which arrive as strings) but changes the data in place. The JSON Schema specification itself treats coercion as out of scope.
FAQ
What are the 7 types in JSON Schema?
JSON Schema defines exactly 7 primitive types: string, number, integer, boolean, array, object, and null. These map to the 6 value types in RFC 8259 (the JSON specification) plus integer, which JSON Schema adds as a constrained subtype of number. Every valid JSON value belongs to exactly one of these 7 categories. The type keyword restricts which category a value may belong to. If you omit type entirely, any JSON value is valid against that schema.
What is the difference between number and integer in JSON Schema?
integer is a subset of number. The value 42 passes both {"type": "number"} and {"type": "integer"}. The value 3.14 passes number but fails integer. Use number when you want to accept any numeric value including decimals. Use integer when you specifically need to reject non-whole numbers — for example, a page count, a port number, or a quantity field. In Ajv, the check is value % 1 === 0, so 42.0 passes integer because its fractional part is zero.
How do I make a JSON Schema field nullable?
Use a type array that includes "null": {"type": ["string", "null"]}. This is the standard nullable pattern in JSON Schema Draft 2019-09 and Draft 2020-12. It works for any base type: ["number", "null"], ["boolean", "null"], ["object", "null"], ["array", "null"]. In OpenAPI 3.0, the non-standard nullable: true extension keyword was used. OpenAPI 3.1, aligned with JSON Schema Draft 2020-12, uses the standard type array form instead.
What does JSON Schema type: "object" validate?
type: "object" accepts any JSON object — a set of key-value pairs in curly braces. By itself it accepts any object regardless of properties: {}, {"a": 1}, {"x": null, "y": [1,2]} all pass. JSON arrays do not pass type: "object" even though in JavaScript typeof [] === "object". To constrain which properties are allowed or required, combine type: "object" with properties, required, and additionalProperties.
Can a JSON Schema field have multiple types?
Yes. Pass an array of type names: {"type": ["string", "number"]} accepts both strings and numbers. The most common multi-type pattern is the nullable field: {"type": ["string", "null"]}. A type array only restricts the primitive type — it does not let you add type-specific constraints like minLength for strings only. For per-type constraints alongside multiple types, use oneOf: {"oneOf": [{"type": "string", "minLength": 1}, {"type": "null"}]}.
What JSON Schema type should I use for dates?
JSON has no native date type — use {"type": "string", "format": "date-time"} for ISO 8601 timestamps like "2026-05-19T10:30:00Z", {"type": "string", "format": "date"} for date-only values like "2026-05-19". The format keyword is advisory by default. In Ajv, install ajv-formats and call addFormats(ajv) to enforce format validation. For Unix timestamps, use {"type": "integer", "minimum": 0}.
Does JSON Schema type coerce values?
No. JSON Schema validation is strict — it does not coerce types. The string "42" fails {"type": "number"}; the number 1 fails {"type": "boolean"}. Ajv has a coerceTypes option that enables coercion (converting "42" to 42), which is useful for validating HTTP query parameters. However, coercion mutates the data object in place, which can cause surprising side effects. The JSON Schema specification itself treats coercion as out of scope.
How does type: "array" work in JSON Schema Draft 2020-12?
In Draft 2020-12, {"type": "array"} with no additional keywords accepts any array of any length with any element types. To constrain elements, use items (one schema for all elements), prefixItems (tuple validation — one schema per index position), minItems, maxItems, and uniqueItems. The items keyword changed between drafts: in Draft 4/7, items could be an array of schemas for tuples. In Draft 2020-12, items is always a single schema for additional items beyond prefixItems. Tuple validation now uses prefixItems.
Further reading and primary sources
- JSON Schema: Types — Official JSON Schema type keyword reference
- JSON Schema: Numeric Types — JSON Schema numeric type keywords