json-schema-library
Version:
Customizable and hackable json-validator and json-schema utilities for traversal, data generation and validation
79 lines (69 loc) • 2.56 kB
text/typescript
import { getValue } from "../utils/getValue";
import { SchemaNode } from "../types";
import {
Keyword,
JsonSchemaResolverParams,
JsonSchemaValidatorParams,
ValidationReturnType,
ValidationAnnotation
} from "../Keyword";
import { isObject } from "../utils/isObject";
import { validateNode } from "../validateNode";
import { collectValidationErrors } from "src/utils/collectValidationErrors";
export const propertiesKeyword: Keyword = {
id: "property",
keyword: "properties",
parse: parseProperties,
addResolve: (node: SchemaNode) => node.properties != null,
resolve: propertyResolver,
addValidate: (node: SchemaNode) => node.properties != null,
validate: validateProperties
};
function propertyResolver({ node, key }: JsonSchemaResolverParams) {
return node.properties?.[key];
}
export function parseProperties(node: SchemaNode) {
const { schema, evaluationPath, schemaLocation } = node;
if (schema.properties == null) {
return;
}
if (schema.properties && !isObject(schema.properties)) {
return node.createError("schema-error", {
pointer: schemaLocation,
schema,
value: undefined,
message: "keyword `properties` must be of type `object`"
});
}
const errors: ValidationAnnotation[] = [];
const parsedProperties: Record<string, SchemaNode> = {};
Object.keys(schema.properties).forEach((propertyName) => {
const propertyNode = node.compileSchema(
schema.properties[propertyName],
`${evaluationPath}/properties/${propertyName}`,
`${schemaLocation}/properties/${propertyName}`
);
parsedProperties[propertyName] = propertyNode;
collectValidationErrors(errors, parsedProperties[propertyName]);
});
node.properties = parsedProperties;
return errors;
}
function validateProperties({ node, data, pointer, path }: JsonSchemaValidatorParams) {
if (!isObject(data)) {
return;
}
// move validation through properties
const errors: ValidationReturnType = [];
const properties = node.properties ?? {};
Object.keys(data).forEach((propertyName) => {
const value = getValue(data, propertyName);
const propertyNode = properties[propertyName];
if (propertyNode == null || value === void 0) {
return;
}
const result = validateNode(propertyNode, value, `${pointer}/${propertyName}`, path);
errors.push(...result);
});
return errors;
}