Schema Model Summary
Core schema structure is represented by Schema and parsed by FileSchemaLoader.
Supported Keyword Groups
- Type and shape:
type,properties,patternProperties,items,prefixItems,required,additionalProperties - Primitive constraints:
minimum,maximum,exclusiveMinimum,exclusiveMaximum,multipleOf,minLength,maxLength,pattern,format,enum,const - Array constraints:
minItems,maxItems,uniqueItems,items,prefixItems,additionalItems - Object constraints:
minProperties,maxProperties,dependencies,dependentRequired,dependentSchemas - Composition:
allOf,anyOf,oneOf,not - Conditional:
if,then,else - Reference:
$ref,definitions,$defs - Metadata:
$schema,$id,title,description
[!NOTE] For complete details on each keyword’s behavior, refer to the Schema keywords reference page.
Construction Pattern: Strict Object Contract
{
"type": "object",
"required": ["id", "name"],
"additionalProperties": false,
"properties": {
"id": {"type": "string"},
"name": {"type": "string", "minLength": 2}
}
}
Use when: You need to enforce a fixed object structure where only specific properties are allowed.
Details:
type: "object"specifies that the data must be a JSON objectrequiredarray lists properties that must be present in the objectadditionalProperties: falseprevents any properties not explicitly defined inproperties- Each property in
propertiesdefines the schema for that specific property
Best Practices:
- Always pair
additionalProperties: falsewithrequiredwhen you want a strict contract - Consider using descriptive titles and descriptions for better documentation
- For optional properties, omit them from the
requiredarray
See Also: Object constraints for more property-related keywords
Construction Pattern: Dictionary/Map Object
{
"type": "object",
"patternProperties": {
"^[a-z0-9_-]+$": {"type": "string"}
},
"additionalProperties": false
}
Use when: You need to accept objects with dynamic keys that follow a specific naming pattern, while rejecting unknown keys.
Details:
type: "object"specifies that the data must be a JSON objectpatternPropertiesdefines a regex pattern that keys must match to be valid- Each matching key’s value must conform to the specified schema (in this case, a string)
additionalProperties: falseprevents any keys that don’t match the pattern from being accepted
Best Practices:
- Test your regex pattern thoroughly to ensure it matches all valid keys and rejects invalid ones
- Consider using more specific patterns when possible (e.g.,
^[a-z][a-z0-9_]*$for identifiers that must start with a letter) - For cases where you want to allow additional properties, set
additionalProperties: trueor provide a schema for them
See Also: Pattern Properties and Additional Properties
Construction Pattern: Typed Homogeneous Array
{
"type": "array",
"items": {
"type": "integer",
"minimum": 0
}
}
Use when: You need to validate arrays where all elements must conform to the same type and constraints.
Details:
type: "array"specifies that the data must be a JSON arrayitemsdefines the schema that all array elements must validate against- In this example, all elements must be integers with a minimum value of 0
Best Practices:
- For complex element schemas, consider extracting them to definitions/$defs for reuse
- Remember that
itemsapplies to all elements whenprefixItemsis not defined - When you need different validation for different positions, consider
prefixItems(tuple validation) instead
See Also: Array constraints for more array-related keywords
Construction Pattern: Array with Constraints
All array constraints are now fully enforced:
{
"type": "array",
"minItems": 1,
"maxItems": 10,
"uniqueItems": true,
"items": {
"type": "object",
"properties": {
"id": {"type": "string"},
"name": {"type": "string"}
}
}
}
Use when: You need to validate arrays with specific size, uniqueness, and element constraints.
Details:
type: "array"specifies that the data must be a JSON arrayminItems: 1requires at least one element in the arraymaxItems: 10limits the array to a maximum of 10 elementsuniqueItems: trueensures all elements in the array are uniqueitemsdefines the schema that all array elements must validate against- In this example, each element must be an object with “id” and “name” string properties
Best Practices:
- Consider whether
uniqueItemsis necessary for your use case, as it can impact performance for large arrays - When you need different validation for different array positions, consider using
prefixItemsinstead of or in addition toitems - For arrays of objects, consider adding
requiredfields to the item schema if certain properties are mandatory
See Also:
- Size constraints for
minItemsandmaxItems - Uniqueness constraint for
uniqueItems - Items validation for the
itemskeyword
Tuple Validation with prefixItems (2019-09/2020-12)
{
"type": "array",
"prefixItems": [
{"type": "string"},
{"type": "integer"},
{"type": "boolean"}
],
"items": false
}
Use when: You need to validate arrays where specific positions have specific types (tuple validation), commonly used for fixed-length arrays with position-dependent types.
Details:
type: "array"specifies that the data must be a JSON arrayprefixItemsdefines schemas for the first N elements of the array (positions 0, 1, 2 in this example)items: falsemeans no additional elements are allowed beyond the prefixItems- Position 0 must be a string, position 1 must be an integer, position 2 must be a boolean
How it works:
- The array must have at least as many elements as there are items in the
prefixItemsarray - Each element at position N must validate against the schema at
prefixItems[N] - When
itemsis set tofalse, no additional elements beyond the prefixItems are allowed - When
itemsis omitted or set to a schema, additional elements must validate against that schema
Best Practices:
- Use
prefixItemsfor fixed-length arrays where position matters (like [name, age, isActive]) - When you need variable-length arrays with consistent element types, use
itemsinstead - Consider using
additionalItems(when combined with prefixItems) to define a schema for extra elements - For complex tuple schemas, consider extracting them to definitions/$defs for reuse
See Also:
- Prefix Items for tuple validation details
- Items for continued array validation
- Additional Items for validating elements beyond prefixItems
Construction Pattern: Object with Property Count Constraints
{
"type": "object",
"minProperties": 1,
"maxProperties": 10,
"properties": {
"name": {"type": "string"},
"email": {"type": "string", "format": "email"}
}
}
Use when: You need to constrain the number of properties in an object while defining specific properties.
Details:
type: "object"specifies that the data must be a JSON objectminProperties: 1requires at least one property to be presentmaxProperties: 10limits the object to a maximum of 10 propertiespropertiesdefines the schema for specific named properties- In this example, the object must have between 1 and 10 properties, with “name” as a string and “email” as a string with email format
Best Practices:
- Consider whether both min and max constraints are necessary for your use case
- When you only need a minimum, omit
maxProperties; when you only need a maximum, omitminProperties - Remember that these constraints count all properties, including those not defined in
properties(unlessadditionalProperties: falseis set) - For objects where you want to allow additional properties while constraining defined ones, omit
additionalProperties: falseor set it totrue
See Also:
- Object constraints for more object-related keywords
- Properties for defining specific property schemas
- Additional Properties for controlling undeclared properties
Construction Pattern: Conditional Rules
{
"type": "object",
"properties": {
"mode": {"type": "string", "enum": ["strict", "loose"]},
"limit": {"type": "integer"}
},
"if": {"properties": {"mode": {"enum": ["strict"]}}},
"then": {"properties": {"limit": {"minimum": 10}}},
"else": {"properties": {"limit": {"minimum": 0}}}
}
Use when: You need to apply different validation rules based on the values of other properties in the same object.
Details:
type: "object"specifies that the data must be a JSON objectpropertiesdefines the schema for the object’s propertiesifspecifies a condition that, when met, triggers thethenschemathendefines the schema to validate against when theifcondition is trueelsedefines the schema to validate against when theifcondition is false- In this example:
- If
modeis “strict”, thenlimitmust be at least 10 - If
modeis not “strict” (i.e., “loose”), thenlimitmust be at least 0 - The
modeproperty must be either “strict” or “loose” due to the enum constraint - The
limitproperty must be an integer
- If
How it works:
- The validator first evaluates the
ifschema against the data - If the
ifvalidation succeeds (no errors), it validates against thethenschema - If the
ifvalidation fails, it validates against theelseschema - Only one of
thenorelseis applied, not both
Best Practices:
- Keep conditional logic simple and easy to understand
- Consider using
dependentRequiredordependentSchemasfor simpler property-based conditions - For complex conditions, consider breaking them into multiple steps or using custom logic outside of JSON Schema
- Test all branches of your conditional logic to ensure they work as expected
See Also:
- Conditional for more details on if/then/else
- Enum for restricting property values
- Dependencies for alternative ways to express property relationships
Construction Pattern: Dependencies
Property Dependencies
{
"type": "object",
"properties": {
"name": {"type": "string"},
"credit_card": {"type": "string"}
},
"dependencies": {
"credit_card": ["billing_address"]
}
}
Use when: You need to make certain properties required based on the presence of other properties in the same object.
Details:
type: "object"specifies that the data must be a JSON objectpropertiesdefines the schema for the object’s propertiesdependenciesspecifies that when certain properties are present, other properties become required- In this example, if the
credit_cardproperty is present, then thebilling_addressproperty becomes required - Note: The
dependencieskeyword here refers to the “dependencies” from older JSON Schema drafts (Draft 04/06/07), which is different fromdependentRequiredanddependentSchemas
How it works:
- When validating an object, if the left-side property (e.g., “credit_card”) is present in the data
- Then all properties listed in the right-side array (e.g., [“billing_address”]) must also be present in the data
- If any required dependency is missing, validation fails
Best Practices:
- Consider using
dependentRequired(JSON Schema Draft 2019-09+) for a more explicit and modern approach - Use
dependencieswhen you need compatibility with older JSON Schema implementations - Clearly document which properties depend on which others for maintainability
See Also:
- Dependencies for the traditional dependencies keyword
- Dependent Required for the modern alternative
- Dependent Schemas for schema-based dependencies
Schema Dependencies
{
"type": "object",
"properties": {
"product": {"type": "string"},
"quantity": {"type": "integer"}
},
"dependencies": {
"quantity": {
"properties": {
"quantity": {"minimum": 1}
},
"required": ["product"]
}
}
}
Use when: You need to apply complex schema constraints based on the presence of a property, combining both property requirements and value constraints.
Details:
type: "object"specifies that the data must be a JSON objectpropertiesdefines the schema for the object’s propertiesdependenciesspecifies that when the left-side property is present, the right-side schema constraints apply- In this example, if the
quantityproperty is present:- The
quantityproperty itself must have a minimum value of 1 - The
productproperty becomes required
- The
- Note: This uses the older “dependencies” keyword syntax (Draft 04/06/07) which allows schema constraints
How it works:
- When validating an object, if the left-side property (e.g., “quantity”) is present in the data
- Then the schema specified on the right-side is applied to the entire data object
- In this case, it adds both a constraint on “quantity” (minimum 1) and makes “product” required
Best Practices:
- Consider using
dependentSchemas(JSON Schema Draft 2019-09+) for a more explicit and modern approach - Use the traditional
dependencieskeyword when you need compatibility with older JSON Schema implementations - Clearly document the implied constraints for maintainability
See Also:
- Dependencies for the traditional dependencies keyword
- Dependent Required for property-based dependencies
- Dependent Schemas for the modern schema-based alternative
Construction Pattern: dependentRequired (2019-09+)
{
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"},
"phone": {"type": "string"}
},
"dependentRequired": {
"email": ["name"],
"phone": ["name"]
}
}
Use when: You need to make certain properties required based on the presence of other properties, using the modern JSON Schema approach.
Details:
type: "object"specifies that the data must be a JSON objectpropertiesdefines the schema for the object’s propertiesdependentRequiredspecifies that when the left-side property is present, the right-side properties become required- In this example:
- If the
emailproperty is present, then thenameproperty becomes required - If the
phoneproperty is present, then thenameproperty becomes required
- If the
- Note: This is the modern replacement for the traditional
dependencieskeyword, introduced in JSON Schema Draft 2019-09
How it works:
- When validating an object, for each property listed in
dependentRequired:- If that property is present in the data
- Then all properties listed in its array value must also be present in the data
- Unlike the traditional
dependencieskeyword,dependentRequiredonly affects requiredness, not other schema constraints
Best Practices:
- Prefer
dependentRequiredover the traditionaldependencieskeyword for modern JSON Schema usage - Use this when you only need to affect requiredness, not other schema aspects of dependent properties
- For cases where you need to apply schema constraints (not just requiredness), consider
dependentSchemas
See Also:
- Dependent Required for more details
- Dependent Schemas for schema-based dependencies
- Dependencies for the traditional alternative
Construction Pattern: dependentSchemas (2019-09+)
{
"type": "object",
"properties": {
"shipping": {"type": "object"},
"billing": {"type": "object"}
},
"dependentSchemas": {
"billing": {
"properties": {
"billing": {},
"billing_address": {"type": "string"}
},
"required": ["billing_address"]
}
}
}
Use when: You need to apply additional schema constraints to the entire object based on the presence of a specific property.
Details:
type: "object"specifies that the data must be a JSON objectpropertiesdefines the schema for the object’s propertiesdependentSchemasspecifies that when the left-side property is present, the right-side schema applies to the entire data object- In this example, if the
billingproperty is present:- The
billingproperty itself must be an object (can be empty) - The
billing_addressproperty becomes required and must be a string
- The
- Note: This is the modern replacement for schema-based dependencies in the traditional
dependencieskeyword, introduced in JSON Schema Draft 2019-09
How it works:
- When validating an object, for each property listed in
dependentSchemas:- If that property is present in the data
- Then the schema specified as its value is applied to the entire data object
- This allows you to conditionally apply complex validation rules based on the presence of certain properties
Best Practices:
- Prefer
dependentSchemasover the traditionaldependencieskeyword for schema-based dependencies in modern JSON Schema - Use this when you need to apply constraints to the whole object based on a property’s presence
- For cases where you only need to affect requiredness (not other schema aspects), consider
dependentRequired
See Also:
- Dependent Schemas for more details
- Dependent Required for property-based requiredness
- Dependencies for the traditional alternative
Construction Pattern: additionalProperties as Schema
{
"type": "object",
"properties": {
"name": {"type": "string"}
},
"additionalProperties": {"type": "string"}
}
Use when: You need to allow additional properties beyond those explicitly defined, but want to constrain their type or schema.
Details:
type: "object"specifies that the data must be a JSON objectpropertiesdefines the schema for specific named propertiesadditionalPropertiesdefines the schema that any undeclared properties must validate against- In this example:
- The “name” property is explicitly defined and must be a string
- Any other properties (not named “name”) must also be strings
- Properties like “id”, “title”, “description” would be valid as long as they are strings
How it works:
- During validation, each property in the object is checked:
- If the property name exists in
properties, it’s validated against that schema - If the property name does not exist in
properties, it’s validated against theadditionalPropertiesschema
- If the property name exists in
- This allows you to be specific about known properties while still allowing flexibility for additional ones
Best Practices:
- Consider whether you want to allow additional properties at all - sometimes
additionalProperties: falseis safer - When allowing additional properties, think about what type or schema makes sense for them
- For complex additional property schemas, consider extracting them to definitions/$defs for reuse
- Remember that
additionalPropertiescan be either a boolean or a schema:true: allows any additional properties (no validation)false: prohibits any additional properties{}: allows any additional properties (empty object schema){"type": "string"}: allows additional properties only if they are strings
See Also:
- Additional Properties for more details
- Properties for defining specific property schemas
Construction Pattern: Exclusive Minimum/Maximum
Modern Numeric Form (2019-09/2020-12)
{
"type": "number",
"exclusiveMinimum": 0,
"exclusiveMaximum": 100
}
This means: value > 0 AND value < 100
Use when: You need to set strict bounds where the limit values themselves are not allowed.
Details:
type: "number"specifies that the data must be a JSON number (integer or floating-point)exclusiveMinimum: 0means the value must be strictly greater than 0 (not equal to 0)exclusiveMaximum: 100means the value must be strictly less than 100 (not equal to 100)- Together, they constrain the value to the range (0, 100)
Legacy Boolean Form (Draft-04/06/07)
{
"type": "number",
"minimum": 0,
"maximum": 100,
"exclusiveMinimum": true,
"exclusiveMaximum": true
}
Use when: You need to use the older boolean form of exclusive constraints for compatibility with legacy JSON Schema validators.
Details:
type: "number"specifies that the data must be a JSON numberminimum: 0andmaximum: 100set the inclusive bounds [0, 100]exclusiveMinimum: trueinverts the minimum to be exclusive (value > 0)exclusiveMaximum: trueinverts the maximum to be exclusive (value < 100)- Together, they constrain the value to the range (0, 100)
Compatibility Note: Both forms are supported and produce identical validation results. The modern numeric form (Direct numbers) is preferred in newer JSON Schema drafts (2019-09+), while the legacy boolean form maintains compatibility with older implementations.
Best Practices:
- Use the modern numeric form for new schemas targeting JSON Schema 2019-09 or later
- Consider adding both forms if you need to support very old JSON Schema validators
- Remember that exclusive constraints cannot be used with
minimum/maximumset to null in the legacy form - For inclusive bounds, use
minimumandmaximumwithout the exclusive flags
See Also:
- Numeric constraints for more details on minimum/maximum
- Exclusive minimum and Exclusive maximum reference pages
Construction Pattern: multipleOf
{
"type": "number",
"multipleOf": 0.5
}
Use when: You need to constrain a numeric value to be a multiple of a specific number, commonly used for currency, measurements, or step-based values.
Details:
type: "number"specifies that the data must be a JSON numbermultipleOf: 0.5means the value must be divisible by 0.5 (e.g., 0, 0.5, 1.0, 1.5, 2.0, etc.)- Works with both integers and floating-point numbers
- The divisor must be a positive number
How it works:
- During validation, the validator checks if
value % multipleOf === 0 - For floating-point numbers, this uses precise floating-point arithmetic
- If the remainder is zero, validation passes
Best Practices:
- Use
multipleOffor values that must follow a specific step pattern - For currency, consider using
multipleOf: 0.01for cent-based precision - For measurements, use appropriate multiples (e.g.,
multipleOf: 0.5for half-unit increments) - Be aware of floating-point precision issues with very small or very large multiples
See Also:
- Numeric constraints for more details
- Multiple of reference page
Construction Pattern: String Length Constraints
{
"type": "string",
"minLength": 3,
"maxLength": 50
}
Use when: You need to constrain the length of a string value, commonly used for usernames, passwords, or text fields.
Details:
type: "string"specifies that the data must be a JSON stringminLength: 3requires the string to have at least 3 charactersmaxLength: 50limits the string to a maximum of 50 characters- Length is measured in Unicode code points (characters)
How it works:
- During validation, the validator checks the string’s length property
- Empty strings have length 0
- Each character counts as 1, regardless of being multi-byte
Best Practices:
- Always set reasonable minimum and maximum lengths for string fields
- Consider user experience when setting minimum lengths (e.g., usernames should be at least 3 characters)
- Set maximum lengths to prevent excessively long inputs
- For passwords, consider both minimum length and complexity requirements
See Also:
- String constraints for more details
- Min length and Max length reference pages
Construction Pattern: String Pattern (Regex)
{
"type": "string",
"pattern": "^[A-Z][a-z]+$"
}
Use when: You need to validate that a string matches a specific regular expression pattern, commonly used for identifiers, codes, or formatted text.
Details:
type: "string"specifies that the data must be a JSON stringpattern: "^[A-Z][a-z]+$"defines a regex pattern that the string must match- In this example, the string must start with an uppercase letter followed by one or more lowercase letters
- The pattern uses JavaScript regex syntax
How it works:
- During validation, the validator tests the string against the regex pattern
- The pattern must match the entire string (implicitly anchored)
- If the pattern matches, validation passes
Best Practices:
- Test your regex patterns thoroughly to ensure they match valid inputs and reject invalid ones
- Use anchors (
^and `— title: Examples and schema construction description: Complete reference patterns for constructing schemas with all supported JSON Schema features. doc_type: reference order: 6 sequence: 15 permalink: /examples-and-schema-construction.html —
Schema Model Summary
Core schema structure is represented by Schema and parsed by FileSchemaLoader.
Supported Keyword Groups
- Type and shape:
type,properties,patternProperties,items,prefixItems,required,additionalProperties - Primitive constraints:
minimum,maximum,exclusiveMinimum,exclusiveMaximum,multipleOf,minLength,maxLength,pattern,format,enum,const - Array constraints:
minItems,maxItems,uniqueItems,items,prefixItems,additionalItems - Object constraints:
minProperties,maxProperties,dependencies,dependentRequired,dependentSchemas - Composition:
allOf,anyOf,oneOf,not - Conditional:
if,then,else - Reference:
$ref,definitions,$defs - Metadata:
$schema,$id,title,description
[!NOTE] For complete details on each keyword’s behavior, refer to the Schema keywords reference page.
Construction Pattern: Strict Object Contract
{
"type": "object",
"required": ["id", "name"],
"additionalProperties": false,
"properties": {
"id": {"type": "string"},
"name": {"type": "string", "minLength": 2}
}
}
Use when: You need to enforce a fixed object structure where only specific properties are allowed.
Details:
type: "object"specifies that the data must be a JSON objectrequiredarray lists properties that must be present in the objectadditionalProperties: falseprevents any properties not explicitly defined inproperties- Each property in
propertiesdefines the schema for that specific property
Best Practices:
- Always pair
additionalProperties: falsewithrequiredwhen you want a strict contract - Consider using descriptive titles and descriptions for better documentation
- For optional properties, omit them from the
requiredarray
See Also: Object constraints for more property-related keywords
Construction Pattern: Dictionary/Map Object
{
"type": "object",
"patternProperties": {
"^[a-z0-9_-]+$": {"type": "string"}
},
"additionalProperties": false
}
Use when: You need to accept objects with dynamic keys that follow a specific naming pattern, while rejecting unknown keys.
Details:
type: "object"specifies that the data must be a JSON objectpatternPropertiesdefines a regex pattern that keys must match to be valid- Each matching key’s value must conform to the specified schema (in this case, a string)
additionalProperties: falseprevents any keys that don’t match the pattern from being accepted
Best Practices:
- Test your regex pattern thoroughly to ensure it matches all valid keys and rejects invalid ones
- Consider using more specific patterns when possible (e.g.,
^[a-z][a-z0-9_]*$for identifiers that must start with a letter) - For cases where you want to allow additional properties, set
additionalProperties: trueor provide a schema for them
See Also: Pattern Properties and Additional Properties
Construction Pattern: Typed Homogeneous Array
{
"type": "array",
"items": {
"type": "integer",
"minimum": 0
}
}
Use when: You need to validate arrays where all elements must conform to the same type and constraints.
Details:
type: "array"specifies that the data must be a JSON arrayitemsdefines the schema that all array elements must validate against- In this example, all elements must be integers with a minimum value of 0
Best Practices:
- For complex element schemas, consider extracting them to definitions/$defs for reuse
- Remember that
itemsapplies to all elements whenprefixItemsis not defined - When you need different validation for different positions, consider
prefixItems(tuple validation) instead
See Also: Array constraints for more array-related keywords
Construction Pattern: Array with Constraints
All array constraints are now fully enforced:
{
"type": "array",
"minItems": 1,
"maxItems": 10,
"uniqueItems": true,
"items": {
"type": "object",
"properties": {
"id": {"type": "string"},
"name": {"type": "string"}
}
}
}
Use when: You need to validate arrays with specific size, uniqueness, and element constraints.
Details:
type: "array"specifies that the data must be a JSON arrayminItems: 1requires at least one element in the arraymaxItems: 10limits the array to a maximum of 10 elementsuniqueItems: trueensures all elements in the array are uniqueitemsdefines the schema that all array elements must validate against- In this example, each element must be an object with “id” and “name” string properties
Best Practices:
- Consider whether
uniqueItemsis necessary for your use case, as it can impact performance for large arrays - When you need different validation for different array positions, consider using
prefixItemsinstead of or in addition toitems - For arrays of objects, consider adding
requiredfields to the item schema if certain properties are mandatory
See Also:
- Size constraints for
minItemsandmaxItems - Uniqueness constraint for
uniqueItems - Items validation for the
itemskeyword
Tuple Validation with prefixItems (2019-09/2020-12)
{
"type": "array",
"prefixItems": [
{"type": "string"},
{"type": "integer"},
{"type": "boolean"}
],
"items": false
}
Use when: You need to validate arrays where specific positions have specific types (tuple validation), commonly used for fixed-length arrays with position-dependent types.
Details:
type: "array"specifies that the data must be a JSON arrayprefixItemsdefines schemas for the first N elements of the array (positions 0, 1, 2 in this example)items: falsemeans no additional elements are allowed beyond the prefixItems- Position 0 must be a string, position 1 must be an integer, position 2 must be a boolean
How it works:
- The array must have at least as many elements as there are items in the
prefixItemsarray - Each element at position N must validate against the schema at
prefixItems[N] - When
itemsis set tofalse, no additional elements beyond the prefixItems are allowed - When
itemsis omitted or set to a schema, additional elements must validate against that schema
Best Practices:
- Use
prefixItemsfor fixed-length arrays where position matters (like [name, age, isActive]) - When you need variable-length arrays with consistent element types, use
itemsinstead - Consider using
additionalItems(when combined with prefixItems) to define a schema for extra elements - For complex tuple schemas, consider extracting them to definitions/$defs for reuse
See Also:
- Prefix Items for tuple validation details
- Items for continued array validation
- Additional Items for validating elements beyond prefixItems
Construction Pattern: Object with Property Count Constraints
{
"type": "object",
"minProperties": 1,
"maxProperties": 10,
"properties": {
"name": {"type": "string"},
"email": {"type": "string", "format": "email"}
}
}
Use when: You need to constrain the number of properties in an object while defining specific properties.
Details:
type: "object"specifies that the data must be a JSON objectminProperties: 1requires at least one property to be presentmaxProperties: 10limits the object to a maximum of 10 propertiespropertiesdefines the schema for specific named properties- In this example, the object must have between 1 and 10 properties, with “name” as a string and “email” as a string with email format
Best Practices:
- Consider whether both min and max constraints are necessary for your use case
- When you only need a minimum, omit
maxProperties; when you only need a maximum, omitminProperties - Remember that these constraints count all properties, including those not defined in
properties(unlessadditionalProperties: falseis set) - For objects where you want to allow additional properties while constraining defined ones, omit
additionalProperties: falseor set it totrue
See Also:
- Object constraints for more object-related keywords
- Properties for defining specific property schemas
- Additional Properties for controlling undeclared properties
Construction Pattern: Conditional Rules
{
"type": "object",
"properties": {
"mode": {"type": "string", "enum": ["strict", "loose"]},
"limit": {"type": "integer"}
},
"if": {"properties": {"mode": {"enum": ["strict"]}}},
"then": {"properties": {"limit": {"minimum": 10}}},
"else": {"properties": {"limit": {"minimum": 0}}}
}
Use when: You need to apply different validation rules based on the values of other properties in the same object.
Details:
type: "object"specifies that the data must be a JSON objectpropertiesdefines the schema for the object’s propertiesifspecifies a condition that, when met, triggers thethenschemathendefines the schema to validate against when theifcondition is trueelsedefines the schema to validate against when theifcondition is false- In this example:
- If
modeis “strict”, thenlimitmust be at least 10 - If
modeis not “strict” (i.e., “loose”), thenlimitmust be at least 0 - The
modeproperty must be either “strict” or “loose” due to the enum constraint - The
limitproperty must be an integer
- If
How it works:
- The validator first evaluates the
ifschema against the data - If the
ifvalidation succeeds (no errors), it validates against thethenschema - If the
ifvalidation fails, it validates against theelseschema - Only one of
thenorelseis applied, not both
Best Practices:
- Keep conditional logic simple and easy to understand
- Consider using
dependentRequiredordependentSchemasfor simpler property-based conditions - For complex conditions, consider breaking them into multiple steps or using custom logic outside of JSON Schema
- Test all branches of your conditional logic to ensure they work as expected
See Also:
- Conditional for more details on if/then/else
- Enum for restricting property values
- Dependencies for alternative ways to express property relationships
Construction Pattern: Dependencies
Property Dependencies
{
"type": "object",
"properties": {
"name": {"type": "string"},
"credit_card": {"type": "string"}
},
"dependencies": {
"credit_card": ["billing_address"]
}
}
Use when: You need to make certain properties required based on the presence of other properties in the same object.
Details:
type: "object"specifies that the data must be a JSON objectpropertiesdefines the schema for the object’s propertiesdependenciesspecifies that when certain properties are present, other properties become required- In this example, if the
credit_cardproperty is present, then thebilling_addressproperty becomes required - Note: The
dependencieskeyword here refers to the “dependencies” from older JSON Schema drafts (Draft 04/06/07), which is different fromdependentRequiredanddependentSchemas
How it works:
- When validating an object, if the left-side property (e.g., “credit_card”) is present in the data
- Then all properties listed in the right-side array (e.g., [“billing_address”]) must also be present in the data
- If any required dependency is missing, validation fails
Best Practices:
- Consider using
dependentRequired(JSON Schema Draft 2019-09+) for a more explicit and modern approach - Use
dependencieswhen you need compatibility with older JSON Schema implementations - Clearly document which properties depend on which others for maintainability
See Also:
- Dependencies for the traditional dependencies keyword
- Dependent Required for the modern alternative
- Dependent Schemas for schema-based dependencies
Schema Dependencies
{
"type": "object",
"properties": {
"product": {"type": "string"},
"quantity": {"type": "integer"}
},
"dependencies": {
"quantity": {
"properties": {
"quantity": {"minimum": 1}
},
"required": ["product"]
}
}
}
Use when: You need to apply complex schema constraints based on the presence of a property, combining both property requirements and value constraints.
Details:
type: "object"specifies that the data must be a JSON objectpropertiesdefines the schema for the object’s propertiesdependenciesspecifies that when the left-side property is present, the right-side schema constraints apply- In this example, if the
quantityproperty is present:- The
quantityproperty itself must have a minimum value of 1 - The
productproperty becomes required
- The
- Note: This uses the older “dependencies” keyword syntax (Draft 04/06/07) which allows schema constraints
How it works:
- When validating an object, if the left-side property (e.g., “quantity”) is present in the data
- Then the schema specified on the right-side is applied to the entire data object
- In this case, it adds both a constraint on “quantity” (minimum 1) and makes “product” required
Best Practices:
- Consider using
dependentSchemas(JSON Schema Draft 2019-09+) for a more explicit and modern approach - Use the traditional
dependencieskeyword when you need compatibility with older JSON Schema implementations - Clearly document the implied constraints for maintainability
See Also:
- Dependencies for the traditional dependencies keyword
- Dependent Required for property-based dependencies
- Dependent Schemas for the modern schema-based alternative
Construction Pattern: dependentRequired (2019-09+)
{
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"},
"phone": {"type": "string"}
},
"dependentRequired": {
"email": ["name"],
"phone": ["name"]
}
}
Use when: You need to make certain properties required based on the presence of other properties, using the modern JSON Schema approach.
Details:
type: "object"specifies that the data must be a JSON objectpropertiesdefines the schema for the object’s propertiesdependentRequiredspecifies that when the left-side property is present, the right-side properties become required- In this example:
- If the
emailproperty is present, then thenameproperty becomes required - If the
phoneproperty is present, then thenameproperty becomes required
- If the
- Note: This is the modern replacement for the traditional
dependencieskeyword, introduced in JSON Schema Draft 2019-09
How it works:
- When validating an object, for each property listed in
dependentRequired:- If that property is present in the data
- Then all properties listed in its array value must also be present in the data
- Unlike the traditional
dependencieskeyword,dependentRequiredonly affects requiredness, not other schema constraints
Best Practices:
- Prefer
dependentRequiredover the traditionaldependencieskeyword for modern JSON Schema usage - Use this when you only need to affect requiredness, not other schema aspects of dependent properties
- For cases where you need to apply schema constraints (not just requiredness), consider
dependentSchemas
See Also:
- Dependent Required for more details
- Dependent Schemas for schema-based dependencies
- Dependencies for the traditional alternative
Construction Pattern: dependentSchemas (2019-09+)
{
"type": "object",
"properties": {
"shipping": {"type": "object"},
"billing": {"type": "object"}
},
"dependentSchemas": {
"billing": {
"properties": {
"billing": {},
"billing_address": {"type": "string"}
},
"required": ["billing_address"]
}
}
}
Use when: You need to apply additional schema constraints to the entire object based on the presence of a specific property.
Details:
type: "object"specifies that the data must be a JSON objectpropertiesdefines the schema for the object’s propertiesdependentSchemasspecifies that when the left-side property is present, the right-side schema applies to the entire data object- In this example, if the
billingproperty is present:- The
billingproperty itself must be an object (can be empty) - The
billing_addressproperty becomes required and must be a string
- The
- Note: This is the modern replacement for schema-based dependencies in the traditional
dependencieskeyword, introduced in JSON Schema Draft 2019-09
How it works:
- When validating an object, for each property listed in
dependentSchemas:- If that property is present in the data
- Then the schema specified as its value is applied to the entire data object
- This allows you to conditionally apply complex validation rules based on the presence of certain properties
Best Practices:
- Prefer
dependentSchemasover the traditionaldependencieskeyword for schema-based dependencies in modern JSON Schema - Use this when you need to apply constraints to the whole object based on a property’s presence
- For cases where you only need to affect requiredness (not other schema aspects), consider
dependentRequired
See Also:
- Dependent Schemas for more details
- Dependent Required for property-based requiredness
- Dependencies for the traditional alternative
Construction Pattern: additionalProperties as Schema
{
"type": "object",
"properties": {
"name": {"type": "string"}
},
"additionalProperties": {"type": "string"}
}
Use when: You need to allow additional properties beyond those explicitly defined, but want to constrain their type or schema.
Details:
type: "object"specifies that the data must be a JSON objectpropertiesdefines the schema for specific named propertiesadditionalPropertiesdefines the schema that any undeclared properties must validate against- In this example:
- The “name” property is explicitly defined and must be a string
- Any other properties (not named “name”) must also be strings
- Properties like “id”, “title”, “description” would be valid as long as they are strings
How it works:
- During validation, each property in the object is checked:
- If the property name exists in
properties, it’s validated against that schema - If the property name does not exist in
properties, it’s validated against theadditionalPropertiesschema
- If the property name exists in
- This allows you to be specific about known properties while still allowing flexibility for additional ones
Best Practices:
- Consider whether you want to allow additional properties at all - sometimes
additionalProperties: falseis safer - When allowing additional properties, think about what type or schema makes sense for them
- For complex additional property schemas, consider extracting them to definitions/$defs for reuse
- Remember that
additionalPropertiescan be either a boolean or a schema:true: allows any additional properties (no validation)false: prohibits any additional properties{}: allows any additional properties (empty object schema){"type": "string"}: allows additional properties only if they are strings
See Also:
- Additional Properties for more details
- Properties for defining specific property schemas
Construction Pattern: Exclusive Minimum/Maximum
Modern Numeric Form (2019-09/2020-12)
{
"type": "number",
"exclusiveMinimum": 0,
"exclusiveMaximum": 100
}
This means: value > 0 AND value < 100
Use when: You need to set strict bounds where the limit values themselves are not allowed.
Details:
type: "number"specifies that the data must be a JSON number (integer or floating-point)exclusiveMinimum: 0means the value must be strictly greater than 0 (not equal to 0)exclusiveMaximum: 100means the value must be strictly less than 100 (not equal to 100)- Together, they constrain the value to the range (0, 100)
Legacy Boolean Form (Draft-04/06/07)
{
"type": "number",
"minimum": 0,
"maximum": 100,
"exclusiveMinimum": true,
"exclusiveMaximum": true
}
Use when: You need to use the older boolean form of exclusive constraints for compatibility with legacy JSON Schema validators.
Details:
type: "number"specifies that the data must be a JSON numberminimum: 0andmaximum: 100set the inclusive bounds [0, 100]exclusiveMinimum: trueinverts the minimum to be exclusive (value > 0)exclusiveMaximum: trueinverts the maximum to be exclusive (value < 100)- Together, they constrain the value to the range (0, 100)
Compatibility Note: Both forms are supported and produce identical validation results. The modern numeric form (Direct numbers) is preferred in newer JSON Schema drafts (2019-09+), while the legacy boolean form maintains compatibility with older implementations.
Best Practices:
- Use the modern numeric form for new schemas targeting JSON Schema 2019-09 or later
- Consider adding both forms if you need to support very old JSON Schema validators
- Remember that exclusive constraints cannot be used with
minimum/maximumset to null in the legacy form - For inclusive bounds, use
minimumandmaximumwithout the exclusive flags
) to match the entire string, not just a substring
- Consider using character classes (
[a-z],[0-9]) for common patterns - For complex patterns, consider breaking them into multiple steps or using custom validation
- Document your regex patterns for maintainability
See Also:
- String constraints for more details
- Pattern reference page
Construction Pattern: Format Validation
{
"type": "string",
"format": "email"
}
Use when: You need to validate that a string conforms to a specific format, such as email, date, URI, etc.
Details:
type: "string"specifies that the data must be a JSON stringformat: "email"validates that the string is a valid email address- JSON Schema defines many built-in formats (email, date, date-time, uri, uuid, etc.)
- Format validation is optional in JSON Schema but commonly used
Common Formats:
email: Valid email addressdate: Date in YYYY-MM-DD formatdate-time: Date and time in ISO 8601 formaturi: Valid URI/URLuuid: Valid UUID (e.g., 550e8400-e29b-41d4-a716-446655440000)ipv4: Valid IPv4 addressipv6: Valid IPv6 address
Best Practices:
- Use format validation for common data types instead of writing custom regex patterns
- Be aware that format validation may not be supported by all validators
- Consider using
patternas a fallback if format validation is not available - Document which formats you’re using for maintainability
See Also:
- Format for more details and supported formats
- String constraints for other string validation options
Construction Pattern: Enum (Enumeration)
{
"type": "string",
"enum": ["active", "inactive", "pending"]
}
Use when: You need to restrict a value to a specific set of allowed values, commonly used for status fields, categories, or options.
Details:
type: "string"specifies that the data must be a JSON stringenum: ["active", "inactive", "pending"]defines the only allowed values- The value must exactly match one of the enum values
- Enum values can be of any type (strings, numbers, objects, arrays, etc.)
How it works:
- During validation, the validator checks if the value is present in the enum array
- Comparison is strict (type and value must match)
- If the value is found in the enum array, validation passes
Best Practices:
- Use enum for values that have a fixed, known set of options
- Keep enum values simple and easy to understand
- Consider using
constinstead ofenumwhen there’s only one allowed value - Document the meaning of each enum value for maintainability
- For large sets of values, consider using
patternor custom validation instead
See Also:
Construction Pattern: Const (Constant Value)
{
"type": "string",
"const": "fixed-value"
}
Use when: You need to enforce that a value must be exactly a specific constant value, commonly used for version fields, types, or fixed identifiers.
Details:
type: "string"specifies that the data must be a JSON stringconst: "fixed-value"defines the only allowed value- The value must exactly match the const value
- Const can be of any type (string, number, object, array, etc.)
How it works:
- During validation, the validator checks if the value is strictly equal to the const value
- Comparison is strict (type and value must match)
- If the value matches exactly, validation passes
Best Practices:
- Use
constwhen there’s only one allowed value - Use
enumwhen there are multiple allowed values - Consider using
constfor version fields, type discriminators, or fixed identifiers - Document why the value is constant for maintainability
See Also:
Construction Pattern: Type Arrays (Nullable Types)
{
"type": ["string", "null"],
"description": "A string that can also be null"
}
Use when: You need to allow a value to be one of multiple types, commonly used for nullable fields or fields that can accept different but related types.
Details:
type: ["string", "null"]specifies that the data must be either a string or a null value- JSON Schema allows arrays of types to create unions
- The order of types in the array does not matter
- At least one type in the array must match for validation to pass
- Null is a distinct type in JSON Schema, separate from “string”, “number”, etc.
How it works:
- During validation, the validator checks if the data matches ANY of the types in the array
- If at least one type matches, validation passes
- If none of the types match, validation fails
Best Practices:
- Use type arrays for nullable fields (combining a type with “null”)
- Consider whether you really need multiple types - sometimes a more specific type is better
- Be aware that
nullis a distinct type - it’s not the same as an empty string or zero - For complex union types, consider using
oneOforanyOfinstead for more flexibility - Document why multiple types are needed for maintainability
See Also:
- Type for more details on the type keyword
- Null type for information about null validation
- OneOf and AnyOf for alternative ways to express type unions
Multiple Types
{
"type": ["string", "number", "integer"],
"description": "Any numeric or string value"
}
Construction Pattern: $ref with JSON Pointer
Local Reference with definitions
{
"definitions": {
"Address": {
"type": "object",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"}
}
}
},
"type": "object",
"properties": {
"billing_address": {"$ref": "#/definitions/Address"},
"shipping_address": {"$ref": "#/definitions/Address"}
}
}
Using $defs (2019-09/2020-12)
{
"$defs": {
"Person": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer", "minimum": 0}
}
}
},
"type": "object",
"properties": {
"author": {"$ref": "#/$defs/Person"},
"reviewer": {"$ref": "#/$defs/Person"}
}
}
Escaping in JSON Pointer
{
"$defs": {
"foo~bar": {
"type": "object"
},
"baz/qux": {
"type": "object"
}
},
"properties": {
"field1": {"$ref": "#/$defs/foo~0bar"},
"field2": {"$ref": "#/$defs/baz~1qux"}
}
}
~0represents~~1represents/
Reference to allOf/anyOf/oneOf Items
{
"type": "object",
"allOf": [
{"$ref": "#/definitions/BaseEntity"},
{"properties": {
"extra": {"type": "string"}
}}
],
"definitions": {
"BaseEntity": {
"type": "object",
"properties": {
"id": {"type": "string"}
}
}
}
}
External Reference with $id
{
"$id": "https://example.com/schemas/person.json",
"type": "object",
"properties": {
"name": {"type": "string"}
}
}
Construction Pattern: Metadata
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schemas/user.json",
"title": "User Profile",
"description": "Schema for user profile validation",
"type": "object",
"properties": {
"username": {
"type": "string",
"title": "Username",
"description": "The user's unique identifier"
},
"email": {
"type": "string",
"format": "email"
}
},
"required": ["username", "email"]
}
Construction Pattern: allOf (Composition)
{
"type": "object",
"allOf": [
{
"properties": {
"name": {"type": "string"}
},
"required": ["name"]
},
{
"properties": {
"age": {"type": "integer", "minimum": 0}
},
"required": ["age"]
}
]
}
Use when: You need to combine multiple schemas and validate that the data satisfies ALL of them, commonly used for composing complex schemas from simpler ones.
Details:
type: "object"specifies that the data must be a JSON objectallOfis an array of schemas that must all validate successfully- In this example, the object must have both “name” (string) and “age” (non-negative integer) properties
- Each schema in the array is applied independently
How it works:
- During validation, the validator checks the data against each schema in the
allOfarray - All schemas must validate successfully for the overall validation to pass
- If any schema fails, the entire validation fails
- Errors from all failing schemas are collected
Best Practices:
- Use
allOfto compose complex schemas from reusable components - Keep each schema in the array focused on a single concern
- Consider extracting common schemas to
definitions/$defsfor reuse - Be aware that
allOfcan impact performance with many schemas - For simple cases, consider merging schemas manually instead of using
allOf
See Also:
- AllOf for more details
- AnyOf and OneOf for alternative composition
- Definitions for reusable schema components
Construction Pattern: anyOf (Composition)
{
"type": "object",
"anyOf": [
{
"properties": {
"email": {"type": "string", "format": "email"}
},
"required": ["email"]
},
{
"properties": {
"phone": {"type": "string", "pattern": "^\\+?[0-9]{10,15}$"}
},
"required": ["phone"]
}
]
}
Use when: You need to validate that the data satisfies AT LEAST ONE of multiple schemas, commonly used for alternative structures or optional combinations.
Details:
type: "object"specifies that the data must be a JSON objectanyOfis an array of schemas where at least one must validate successfully- In this example, the object must have either an “email” property (valid email format) OR a “phone” property (valid phone pattern)
- The object can have both properties, but at least one is required
How it works:
- During validation, the validator checks the data against each schema in the
anyOfarray - At least one schema must validate successfully for the overall validation to pass
- If all schemas fail, the entire validation fails
- The validator typically stops at the first successful schema
Best Practices:
- Use
anyOffor alternative structures or optional combinations - Keep each schema in the array focused on a single alternative
- Consider using
oneOfinstead if exactly one schema must match - Be aware that
anyOfcan impact performance with many schemas - Document the alternatives clearly for maintainability
See Also:
Construction Pattern: oneOf (Composition)
{
"type": "object",
"oneOf": [
{
"properties": {
"type": {"const": "user"},
"username": {"type": "string"}
},
"required": ["type", "username"]
},
{
"properties": {
"type": {"const": "admin"},
"permissions": {"type": "array", "items": {"type": "string"}}
},
"required": ["type", "permissions"]
}
]
}
Use when: You need to validate that the data satisfies EXACTLY ONE of multiple schemas, commonly used for discriminated unions or mutually exclusive structures.
Details:
type: "object"specifies that the data must be a JSON objectoneOfis an array of schemas where exactly one must validate successfully- In this example, the object must be either a “user” (with username) OR an “admin” (with permissions), but not both
- The “type” property acts as a discriminator to determine which schema applies
How it works:
- During validation, the validator checks the data against each schema in the
oneOfarray - Exactly one schema must validate successfully for the overall validation to pass
- If zero or more than one schema validates, the entire validation fails
- This ensures mutual exclusivity among the alternatives
Best Practices:
- Use
oneOffor discriminated unions or mutually exclusive structures - Include a discriminator property (like “type”) to clearly identify which schema applies
- Keep each schema in the array focused on a single alternative
- Be aware that
oneOfcan impact performance with many schemas - Consider using
anyOfif multiple schemas can match simultaneously
See Also:
Construction Pattern: not (Composition)
{
"type": "object",
"not": {
"properties": {
"status": {"enum": ["deleted", "banned"]}
},
"required": ["status"]
}
}
Use when: You need to validate that the data does NOT match a specific schema, commonly used for exclusions or negative constraints.
Details:
type: "object"specifies that the data must be a JSON objectnotis a schema that the data must NOT validate against- In this example, the object must NOT have a “status” property with value “deleted” or “banned”
- The object can have any other status value or no status at all
How it works:
- During validation, the validator checks the data against the
notschema - If the data validates successfully against the
notschema, the overall validation fails - If the data fails to validate against the
notschema, the overall validation passes - This is a logical negation operation
Best Practices:
- Use
notfor exclusions or negative constraints - Keep the
notschema simple and focused on what should be excluded - Consider using
enumorpatternfor simpler exclusions - Be aware that
notcan be confusing for complex schemas - Document what is being excluded for maintainability
See Also:
Construction Pattern: additionalItems with prefixItems
{
"type": "array",
"prefixItems": [
{"type": "string"},
{"type": "integer"}
],
"additionalItems": {"type": "boolean"}
}
Use when: You need to validate arrays where the first N elements have specific types (tuple validation) and remaining elements must conform to a specific schema.
Details:
type: "array"specifies that the data must be a JSON arrayprefixItemsdefines schemas for the first 2 elements (positions 0 and 1)additionalItemsdefines the schema for any elements beyond the prefixItems- In this example:
- Position 0 must be a string
- Position 1 must be an integer
- Any additional elements (positions 2+) must be booleans
How it works:
- During validation, the validator checks each element:
- If the position is within
prefixItems, it validates against that schema - If the position is beyond
prefixItems, it validates against theadditionalItemsschema
- If the position is within
- If
additionalItemsisfalse, no additional elements are allowed - If
additionalItemsistrueor omitted, any additional elements are allowed
Best Practices:
- Use
additionalItemswhen you need to validate elements beyond the tuple - Set
additionalItems: falseto enforce a fixed-length tuple - Consider using
itemsinstead for homogeneous arrays - Document the expected array structure for maintainability
See Also:
- Additional Items for more details
- Prefix Items for tuple validation
- Items for homogeneous array validation
Related Pages
- Keyword matrix: Schema keywords
- Runtime rule order: Validation behavior
- Practical examples: Examples