json-schema-library
Version:
Customizable and hackable json-validator and json-schema utilities for traversal, data generation and validation
82 lines (72 loc) • 2.88 kB
text/typescript
import { mergeSchema } from "../utils/mergeSchema";
import { Keyword, JsonSchemaReducerParams, JsonSchemaValidatorParams, ValidationAnnotation } from "../Keyword";
import { SchemaNode } from "../types";
import { validateNode } from "../validateNode";
import { collectValidationErrors } from "src/utils/collectValidationErrors";
const KEYWORD = "anyOf";
export const anyOfKeyword: Keyword = {
id: KEYWORD,
keyword: KEYWORD,
parse: parseAnyOf,
addReduce: (node) => node[KEYWORD] != null,
reduce: reduceAnyOf,
addValidate: (node) => node[KEYWORD] != null,
validate: validateAnyOf
};
export function parseAnyOf(node: SchemaNode) {
const { schema, evaluationPath, schemaLocation } = node;
if (schema[KEYWORD] == null) {
return;
}
if (!Array.isArray(schema[KEYWORD])) {
return node.createError("schema-error", {
pointer: schemaLocation,
schema,
value: schema[KEYWORD],
message: `Keyword '${KEYWORD}' must be an array - received '${typeof schema[KEYWORD]}'`
});
}
if (schema[KEYWORD].length === 0) {
return;
}
node[KEYWORD] = schema[KEYWORD].map((s, index) =>
node.compileSchema(s, `${evaluationPath}/${KEYWORD}/${index}`, `${schemaLocation}/${KEYWORD}/${index}`)
);
return collectValidationErrors([], ...node[KEYWORD]);
}
function reduceAnyOf({ node, data, pointer, path }: JsonSchemaReducerParams) {
if (node[KEYWORD] == null) {
return;
}
let mergedSchema = {};
let dynamicId = "";
for (let i = 0; i < node[KEYWORD].length; i += 1) {
if (validateNode(node[KEYWORD][i], data, pointer, path).length === 0) {
const { node: schemaNode } = node[KEYWORD][i].reduceNode(data);
if (schemaNode) {
const nestedDynamicId = schemaNode.dynamicId?.replace(node.dynamicId, "") ?? "";
const localDynamicId = nestedDynamicId === "" ? `${KEYWORD}/${i}` : nestedDynamicId;
dynamicId += `${dynamicId === "" ? "" : ","}${localDynamicId}`;
const schema = mergeSchema(node[KEYWORD][i].schema, schemaNode.schema);
mergedSchema = mergeSchema(mergedSchema, schema, KEYWORD);
}
}
}
return node.compileSchema(
mergedSchema,
`${node.evaluationPath}${dynamicId}`,
node.schemaLocation,
`${node.schemaLocation}(${dynamicId})`
);
}
function validateAnyOf({ node, data, pointer, path }: JsonSchemaValidatorParams) {
if (node[KEYWORD] == null) {
return;
}
for (const anyOf of node[KEYWORD]) {
if (validateNode(anyOf, data, pointer, path).length === 0) {
return undefined;
}
}
return node.createError("any-of-error", { pointer, schema: node.schema, value: data, anyOf: node.schema[KEYWORD] });
}