Design a JSON Schema Validator
DocuSignSoftware Engineer · OnsiteLast updated
Design and implement a modular JSON schema validator that verifies data against structural schemas, supporting primitive types, nested objects, arrays, regex patterns, numeric ranges, and strict field controls.
Problem Statement
In document processing and API integration platforms like DocuSign, incoming payloads must be strictly validated against predefined contracts before execution.
Implement a JSONSchemaValidator class that validates arbitrary JSON-like data against a simplified JSON schema specification. The validator must return whether the data is valid and a list of human-readable error descriptions if it is not.
Supported Schema Keywords
type: Matches target data type:"string","number"(accepts float or int),"boolean","object", or"array".- Numeric constraints (for
type: "number"):minimum: value must be>= minimum.maximum: value must be<= maximum.
- String constraints (for
type: "string"):pattern: a regular expression string that the value must match (via full or partial match per regex definition).
- Object constraints (for
type: "object"):properties: a dictionary mapping property names to sub-schemas.required: a list of property names that must be present.additionalProperties: boolean. IfFalse, no fields outside ofpropertiesare allowed (defaults toTrue).
- Array constraints (for
type: "array"):items: a sub-schema that every element in the array must satisfy.
Class Interface
class JSONSchemaValidator:
def validate(self, schema: dict, data: any) -> tuple[bool, list[str]]:
"""
Validates `data` against `schema`.
Returns (True, []) if valid, or (False, [error_messages]) if invalid.
"""
pass
Example 1
schema = {
"type": "object",
"required": ["name", "age"],
"additionalProperties": False,
"properties": {
"name": {"type": "string", "pattern": r"^[A-Za-z ]+$"},
"age": {"type": "number", "minimum": 18, "maximum": 120}
}
}
data = {"name": "Alice", "age": 25}
validator = JSONSchemaValidator()
is_valid, errors = validator.validate(schema, data)
# is_valid: True, errors: []
Example 2
data_invalid = {"name": "Alice", "age": 15, "extra": True}
is_valid, errors = validator.validate(schema, data_invalid)
# is_valid: False
# errors: ["age must be >= 18", "unexpected property: extra"]
Constraints
- The provided
schemais guaranteed to be syntactically valid. - Nesting depth of objects/arrays will not exceed 20 levels.
datamay containNone,bool,int,float,str,list, ordict.- Note: in Python,
isinstance(True, int)evaluates toTrue. Make sure boolean values are not mistakenly identified as numbers.
Hints
Hint 1
Beware of Python's type hierarchy where `bool` is a subclass of `int`; check for `bool` explicitly before evaluating numeric types.
Hint 2
Use recursion for nested objects and arrays, passing down a field path (e.g., `user.addresses[0]`) to build informative error messages.
Hint 3
Structure your validation rules using the Strategy or Dispatch pattern (e.g., helper methods per keyword or type) so adding new validation keywords requires minimal code changes.
Follow-up questions
- How would you extend this validator to support schema references (`$ref`) and circular definitions?
- If regex patterns come from untrusted user schemas, how would you protect the validator against Regular Expression Denial of Service (ReDoS)?
- How would you optimize validation if the same schema is executed across millions of requests per minute?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.