1. /**
  2. * Validates JSON payloads for development use with synchronous execution.
  3. *
  4. * @param {object} schema - The JSON schema to validate against.
  5. * @param {object} data - The JSON data to validate.
  6. * @returns {object} - An object containing validation results. {valid: boolean, errors: array}
  7. */
  8. function validateJson(schema, data) {
  9. const errors = [];
  10. if (typeof schema !== 'object' || schema === null) {
  11. return { valid: false, errors: [{ message: 'Schema must be an object.' }] };
  12. }
  13. if (typeof data !== 'object' || data === null) {
  14. return { valid: false, errors: [{ message: 'Data must be an object.' }] };
  15. }
  16. function validateProperty(propertyName, schemaProperty, dataValue) {
  17. if (schemaProperty.required && !dataValue.hasOwnProperty(propertyName)) {
  18. errors.push({ message: `Missing required property: ${propertyName}` });
  19. return;
  20. }
  21. if (schemaProperty.type) {
  22. switch (schemaProperty.type) {
  23. case 'string':
  24. if (typeof dataValue !== 'string') {
  25. errors.push({ message: `Property ${propertyName} must be a string.` });
  26. }
  27. break;
  28. case 'number':
  29. if (typeof dataValue !== 'number' || isNaN(dataValue)) {
  30. errors.push({ message: `Property ${propertyName} must be a number.` });
  31. }
  32. break;
  33. case 'boolean':
  34. if (typeof dataValue !== 'boolean') {
  35. errors.push({ message: `Property ${propertyName} must be a boolean.` });
  36. }
  37. break;
  38. case 'array':
  39. if (!Array.isArray(dataValue)) {
  40. errors.push({ message: `Property ${propertyName} must be an array.` });
  41. }
  42. break;
  43. case 'object':
  44. if (typeof dataValue !== 'object' || dataValue === null) {
  45. errors.push({ message: `Property ${propertyName} must be an object.` });
  46. }
  47. break;
  48. default:
  49. console.warn(`Unknown type: ${schemaProperty.type} for property ${propertyName}`);
  50. }
  51. }
  52. if (schemaProperty.enum && !schemaProperty.enum.includes(dataValue)) {
  53. errors.push({ message: `Property ${propertyName} must be one of: ${schemaProperty.enum.join(', ')}` });
  54. }
  55. if (schemaProperty.minLength && String(dataValue).length < schemaProperty.minLength) {
  56. errors.push({ message: `Property ${propertyName} must be at least ${schemaProperty.minLength} characters long.` });
  57. }
  58. if (schemaProperty.maxLength && String(dataValue).length > schemaProperty.maxLength) {
  59. errors.push({ message: `Property ${propertyName} must be at most ${schemaProperty.maxLength} characters long.` });
  60. }
  61. if (schemaProperty.pattern && !new RegExp(schemaProperty.pattern).test(String(dataValue))) {
  62. errors.push({ message: `Property ${propertyName} must match pattern: ${schemaProperty.pattern}` });
  63. }
  64. if (schemaProperty.properties) {
  65. if (typeof schemaProperty.properties !== 'object' || schemaProperty.properties === null) {
  66. errors.push({message: `Properties must be an object`});
  67. return;
  68. }
  69. for (const propName in schemaProperty.properties) {
  70. if (schemaProperty.properties.hasOwnProperty(propName)) {
  71. validateProperty(propName, schemaProperty.properties[propName], dataValue);
  72. }
  73. }
  74. }
  75. }
  76. for (const key in schema) {
  77. if (schema.hasOwnProperty(key)) {
  78. const schemaProperty = schema[key];
  79. if (typeof schemaProperty === 'object' && schemaProperty !== null) {
  80. if (Array.isArray(schemaProperty)) {
  81. for(const item of schemaProperty){
  82. if(typeof item === 'object' && item !== null){
  83. validateProperty(key, item, data[key]);
  84. } else {
  85. errors.push({message: `Invalid item in array at key ${key}` });
  86. }
  87. }
  88. } else {
  89. validateProperty(key, schemaProperty, data[key]);
  90. }
  91. }

Add your comment