Skip to content

How to Validate Properties in Python Dictionaries

Learn how to validate Python dictionary keys, types, and constraints to prevent KeyError, TypeError, and logical data issues while processing configurations or API responses.

In Python, dictionaries are the go-to structure for handling dynamic data, configurations, and API responses. However, because dictionaries are mutable and schema-less by default, accessing missing keys or processing incorrect data types can lead to runtime errors like KeyError or TypeError.

This guide explores robust techniques to validate dictionary properties, ensuring data integrity through existence checks, type validation, and logical constraint verification.

Validating Key Existence

The most common error when working with dictionaries is the KeyError, which occurs when trying to access a key that does not exist.

Using in and .get()

user_data = {"name": "John", "role": "admin"}

try:
    email = user_data["email"]
except KeyError as e:
    print(f"Error: Missing key {e}")

if "email" in user_data:
    print(f"Email: {user_data['email']}")
else:
    print("Email not found.")

email_safe = user_data.get("email", "No Email Provided")
print(f"Result: {email_safe}")

Output:

Error: Missing key 'email'
Email not found.
Result: No Email Provided

Validating Value Types

Ensuring that a value corresponds to a specific data type (e.g., age must be an int) prevents downstream calculation errors.

Using isinstance()

data = {
    "age": "twenty-five",  # Incorrect type
    "active": True
}

try:
    next_age = data["age"] + 1
except TypeError as e:
    print(f"Math Error: {e}")

def validate_age_type(record):
    if not isinstance(record.get("age"), int):
        print("Validation Failed: 'age' must be an integer.")
        return False
    return True

validate_age_type(data)

Output:

Math Error: can only concatenate str (not "int") to str
Validation Failed: 'age' must be an integer.

Batch Type Validation

You can validate an entire dictionary against a schema of expected types.

def validate_schema(data, schema):
    return all(isinstance(data.get(k), t) for k, t in schema.items())

user_input = {"name": "Alice", "id": 101}
expected_schema = {"name": str, "id": int}

is_valid = validate_schema(user_input, expected_schema)
print(f"Schema Valid: {is_valid}")

Output:

Schema Valid: True

Validating Value Constraints (Ranges)

Sometimes data is the correct type (e.g., an integer) but logically invalid (e.g., a negative age). This requires value checking.

def validate_constraints(data):
    age = data.get("age")
    
    if not isinstance(age, int):
        return False, "Age must be an integer"
    
    if not (0 <= age <= 120):
        return False, f"Age {age} is out of valid range (0-120)"
        
    return True, "Valid"

print(validate_constraints({"age": 150}))
print(validate_constraints({"age": 25}))

Output:

(False, 'Age 150 is out of valid range (0-120)')
(True, 'Valid')

Comprehensive Validation Pattern

For production code, it is best to combine existence, type, and constraint checks into a robust validator function or class.

class DictionaryValidationError(Exception):
    pass

def validate_user_profile(profile):
    schema = {
        "username": (str, lambda x: len(x) >= 3),
        "age":      (int, lambda x: x > 0),
        "email":    (str, lambda x: "@" in x)
    }

    for key, (expected_type, validator) in schema.items():
        if key not in profile:
            raise DictionaryValidationError(f"Missing required key: '{key}'")
        
        value = profile[key]
        
        if not isinstance(value, expected_type):
            raise DictionaryValidationError(
                f"Incorrect type for '{key}'. Expected {expected_type.__name__}, got {type(value).__name__}"
            )
            
        if not validator(value):
            raise DictionaryValidationError(f"Invalid value for '{key}': {value}")

    print("Profile is valid.")

try:
    user = {"username": "Jo", "age": 30, "email": "jo@test.com"}
    validate_user_profile(user)
except DictionaryValidationError as e:
    print(f"Validation Error: {e}")

Output:

Validation Error: Invalid value for 'username': Jo

Conclusion

Proper dictionary validation involves three steps:

  1. Existence: Check if keys exist using in or .get().
  2. Type: Ensure values are of the expected class using isinstance().
  3. Constraint: Verify values meet logical requirements (ranges, length, format).

By implementing these checks, you prevent data corruption and ensure your application handles external input gracefully.

Navigation