UNPKG

@flagpolejs/json-validator

Version:

Simple JSON validator that is similar to JSON Schema format, but with some simplified format that is more readable

192 lines 6.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ValidationError = void 0; class ValidationError { } exports.ValidationError = ValidationError; function getType(value) { if (value === undefined) { return "undefined"; } if (value === null) { return "null"; } const myType = typeof value; if (Array.isArray(value)) { return "array"; } if (myType === "object") { return "object"; } if (myType == "boolean") { return "boolean"; } if (myType == "number") { return "number"; } return "string"; } class JsonValidator { constructor(schema) { this._errors = []; this.compile(schema); } static validate(schema, document) { const validator = new JsonValidator(schema); validator.validate(document); return validator; } get isValid() { return this._errors.length === 0; } get errors() { return this._errors; } compile(schema) { this._schema = typeof schema === "string" ? JSON.parse(schema) : schema; return this.validate; } validate(root) { this._errors = []; this._isValid(this._schema, root, "$"); return this; } _logError(error) { this._errors.push(error); } _matchesType(schema, document, path) { const [schemaType, docType] = this.compareTypes(schema, document); if (schemaType != "undefined") { if (schemaType == "string") { if (docType != schema) { this._logError({ keyword: "type", instancePath: path, message: `must be ${schemaType}, but it was ${docType}`, }); return false; } } else if (schemaType == "array") { const allowedTypes = schema; if (allowedTypes.indexOf(docType) < 0) { const oneOfType = allowedTypes.join(" | "); this._logError({ keyword: "type", instancePath: path, message: `must be ${oneOfType}, but it was ${docType}`, }); return false; } } } return true; } _matchesEnum(schema, document, path) { if (getType(schema) == "array") { if (schema.indexOf(document) < 0) { const enumVals = schema.join(", "); this._logError({ keyword: "value", instancePath: path, message: `value must be in enum ${enumVals}, but it was ${document}`, }); return false; } } return true; } _matchesPattern(schema, document, path) { const [schemaType] = this.compareTypes(schema, document); if (schemaType != "undefined" && !new RegExp(schema).test(String(document))) { this._logError({ keyword: "value", instancePath: path, message: `value ${document} did not match ${String(schema)}`, }); return false; } return true; } _matchesItems(schema, document, path) { const [schemaType, docType] = this.compareTypes(schema, document); if (schemaType != "undefined") { if (docType != "array") { this._logError({ keyword: "schema", instancePath: path, message: `must be an array, but schema defines items.`, }); return false; } return document.every((subItem, index) => { if (schemaType == "string" || schemaType == "array") { return this._matchesType(schema, subItem, `${path}[${index}]`); } else if (schemaType == "object") { return this._isValid(schema, subItem, `${path}[${index}]`); } return true; }); } return true; } compareTypes(schema, document) { return [getType(schema), getType(document)]; } _matchesProperties(schema, document, path) { const [schemaType, docType] = this.compareTypes(schema, document); if (schemaType != "undefined") { if (docType != "object") { this._logError({ keyword: "schema", instancePath: "path", message: `must be an object, but schema defines properties.`, }); return false; } if (schemaType == "string" || schemaType == "array") { return Object.keys(document).every((key) => { return this._matchesType(schema, document[key], `${path}.${key}`); }); } if (schemaType == "object") { return Object.keys(schema).every((key) => { return this._isValid(schema[key], document[key], `${path}.${key}`); }); } } return true; } _isValid(schema, document, path) { const [schemaType] = this.compareTypes(schema, document); if (schemaType == "string" || schemaType == "array") { if (!this._matchesType(schema, document, path)) { return false; } } else if (schemaType == "object") { if (!this._matchesType(schema.type, document, path)) { if (!schema.optional || typeof document != "undefined") { return false; } } if (!this._matchesEnum(schema.enum, document, path)) { return false; } if (!this._matchesPattern(schema.matches, document, path)) { return false; } if (!this._matchesItems(schema.items, document, path)) { return false; } if (!this._matchesProperties(schema.properties, document, path)) { return false; } } return true; } } exports.default = JsonValidator; //# sourceMappingURL=index.js.map