Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

JSON Schema Validation in Python: A Practical Guide

Tech May 14 1

Installation

First, install the required library:

pip install jsonschema

Validating Basic Data Types

The fololwing example demonstrates validating an object with string and numeric fields:

from jsonschema import validate

definition = {
    "type": "object",
    "properties": {
        "product_name": {"type": "string"},
        "unit_price": {"type": "number"},
        "quantity": {"type": "integer"}
    }
}

# Valid input - passes validation
validate(
    instance={"product_name": "Wireless Mouse", "unit_price": 29.99, "quantity": 5},
    schema=definition
)

# Invalid input - string provided instead of number
validate(
    instance={"product_name": "Keyboard", "unit_price": "fifty"},
    schema=definition
)

Validating Arrays with Speciifc Element Types

This example shows how to validate an array where each element must be of a sepcific type:

from jsonschema import validate

definition = {
    "type": "object",
    "properties": {
        "categories": {
            "type": "array",
            "items": {
                "type": "string"
            }
        }
    }
}

# Valid: array of strings
validate(
    instance={"categories": ["electronics", "furniture", "clothing"]},
    schema=definition
)

# Invalid: array contains integers instead of strings
validate(
    instance={"categories": [1, 2, 3]},
    schema=definition
)

Enum Validation

Use the enum keyword to restrict a field to specific allowed values:

from jsonschema import validate

definition = {
    "type": "object",
    "properties": {
        "status": {"enum": ["active", "inactive", "pending"]}
    }
}

# Valid: status is one of the allowed values
validate(
    instance={"status": "active"},
    schema=definition
)

# Invalid: status value not in the enum
validate(
    instance={"status": "unknown"},
    schema=definition
)

Requiring Specific Fields

The required keyword ensures certain fields must be present in the object:

from jsonschema import validate

definition = {
    "type": "object",
    "properties": {
        "username": {"type": "string", "minLength": 3, "maxLength": 50},
        "email": {"type": "string", "format": "email"},
        "role": {"enum": ["admin", "user", "guest"]}
    },
    "required": ["username", "email"]
}

# Valid: both required fields present
validate(
    instance={"username": "john_doe", "email": "john@example.com"},
    schema=definition
)

# Invalid: missing required 'email' field
validate(
    instance={"username": "jane_doe"},
    schema=definition
)

Validating Nested Structures

JSON Schema supports complex nested objects with their own validation rules:

from jsonschema import validate

definition = {
    "type": "object",
    "properties": {
        "order_id": {"type": "integer", "minimum": 1},
        "customer": {
            "type": "object",
            "properties": {
                "full_name": {"type": "string"},
                "address": {"type": "string"},
                "phone": {"type": "string", "pattern": "^[0-9]{10}$"}
            },
            "required": ["full_name", "address", "phone"]
        },
        "items": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "product_id": {"type": "integer"},
                    "quantity": {"type": "integer", "minimum": 1}
                },
                "required": ["product_id", "quantity"]
            }
        }
    },
    "required": ["order_id", "customer", "items"]
}

validate(
    instance={
        "order_id": 1001,
        "customer": {
            "full_name": "Alice Smith",
            "address": "123 Main Street",
            "phone": "1234567890"
        },
        "items": [
            {"product_id": 101, "quantity": 2},
            {"product_id": 102, "quantity": 1}
        ]
    },
    schema=definition
)

Integration with Django REST Framework

Here's a practical example of using JSON Schema validation in a Django API endpoint:

from jsonschema import validate
from jsonschema import ValidationError
from functools import wraps
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.exceptions import APIException


class RequestValidationException(APIException):
    status_code = 400
    default_detail = "Request validation failed"
    default_code = "validation_error"


def validate_request(schema):
    def decorator(view_func):
        @wraps(view_func)
        def wrapper(self, request, *args, **kwargs):
            try:
                validate(instance=request.data, schema=schema)
            except ValidationError as error:
                raise RequestValidationException(
                    detail={"error": error.message, "field": ".".join(str(p) for p in error.path)}
                )
            return view_func(self, request, *args, **kwargs)
        return wrapper
    return decorator


class UserRegistrationView(APIView):
    @validate_request({
        "type": "object",
        "properties": {
            "username": {"type": "string", "minLength": 3, "maxLength": 30},
            "password": {"type": "string", "minLength": 8},
            "profile": {
                "type": "object",
                "properties": {
                    "full_name": {"type": "string"},
                    "department": {"type": "string"},
                    "employee_id": {"type": "string", "minLength": 5}
                },
                "required": ["full_name", "department", "employee_id"]
            }
        },
        "required": ["username", "password", "profile"]
    })
    def post(self, request):
        # Process valid request here
        return Response({"message": "User registered successfully"})

Sample valid request payload:

{
    "username": "admin_user",
    "password": "securepass123",
    "profile": {
        "full_name": "Robert Johnson",
        "department": "Engineering",
        "employee_id": "EMP001"
    }
}

Additional Resources

For more advanced JSON Schema features and specifications, refer to the official documentation:

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.