1. import json
  2. import re
  3. def validate_api_payload(payload, schema):
  4. """
  5. Validates an API payload against a predefined schema.
  6. Args:
  7. payload (dict): The API payload to validate.
  8. schema (dict): A dictionary defining the expected schema.
  9. Returns:
  10. bool: True if the payload is valid, False otherwise.
  11. """
  12. try:
  13. # Check if the payload is valid JSON
  14. json.loads(json.dumps(payload))
  15. except json.JSONDecodeError:
  16. print("Error: Invalid JSON payload.")
  17. return False
  18. for field, details in schema.items():
  19. if field not in payload:
  20. print(f"Error: Missing field: {field}")
  21. return False
  22. expected_type = details.get("type")
  23. if expected_type:
  24. if expected_type == "string":
  25. if not isinstance(payload[field], str):
  26. print(f"Error: Field '{field}' should be a string.")
  27. return False
  28. elif expected_type == "integer":
  29. if not isinstance(payload[field], int):
  30. print(f"Error: Field '{field}' should be an integer.")
  31. return False
  32. elif expected_type == "float":
  33. if not isinstance(payload[field], (int, float)):
  34. print(f"Error: Field '{field}' should be a float.")
  35. return False
  36. elif expected_type == "boolean":
  37. if not isinstance(payload[field], bool):
  38. print(f"Error: Field '{field}' should be a boolean.")
  39. return False
  40. elif expected_type == "list":
  41. if not isinstance(payload[field], list):
  42. print(f"Error: Field '{field}' should be a list.")
  43. return False
  44. elif expected_type == "dict":
  45. if not isinstance(payload[field], dict):
  46. print(f"Error: Field '{field}' should be a dictionary.")
  47. return False
  48. if "required" in details and field in details["required"] and not payload[field]:
  49. print(f"Error: Field '{field}' is required and cannot be empty.")
  50. return False
  51. if "pattern" in details:
  52. pattern = re.compile(details["pattern"])
  53. if not pattern.match(str(payload[field])):
  54. print(f"Error: Field '{field}' does not match pattern: {details['pattern']}")
  55. return False
  56. return True
  57. if __name__ == '__main__':
  58. # Example Usage
  59. schema = {
  60. "user_id": {"type": "integer"},
  61. "username": {"type": "string"},
  62. "email": {"type": "string", "pattern": r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"},
  63. "is_active": {"type": "boolean"},
  64. "roles": {"type": "list"},
  65. "details": {"type": "dict"}
  66. }
  67. payload1 = {
  68. "user_id": 123,
  69. "username": "john.doe",
  70. "email": "john.doe@example.com",
  71. "is_active": True,
  72. "roles": ["admin", "editor"],
  73. "details": {"created_at": "2023-10-27"}
  74. }
  75. payload2 = {
  76. "username": "jane doe",
  77. "email": "invalid-email",
  78. "is_active": "yes"
  79. }
  80. print(f"Payload 1 is valid: {validate_api_payload(payload1, schema)}")
  81. print(f"Payload 2 is valid: {validate_api_payload(payload2, schema)}")

Add your comment