Валидация структур данных в Ajv строится на декларативном описании правил, где зависимости между полями объекта играют ключевую роль при моделировании сложных бизнес-ограничений. Зависимости позволяют связывать свойства так, чтобы наличие или значение одного поля автоматически влияло на требования к другим.
dependenciesМеханизм dependencies в спецификации JSON Schema
Draft-07 представляет два основных режима работы: списочные зависимости
и схемные зависимости.
Списочные зависимости задают обязательные поля, которые должны присутствовать вместе с указанным свойством.
const schema = {
type: "object",
properties: {
creditCard: { type: "string" },
billingAddress: { type: "string" },
cvv: { type: "string" }
},
dependencies: {
creditCard: ["billingAddress", "cvv"]
}
};
В этом случае наличие creditCard автоматически делает
обязательными billingAddress и cvv. Если
creditCard отсутствует, ограничения не применяются.
Схемные зависимости позволяют описывать полноценную валидационную логику для набора свойств:
const schema = {
type: "object",
properties: {
role: { type: "string" },
permissions: { type: "array", items: { type: "string" } }
},
dependencies: {
role: {
properties: {
permissions: {
minItems: 1
}
},
required: ["permissions"]
}
}
};
Здесь при наличии role объект обязан содержать
permissions, причём массив должен соответствовать
дополнительным ограничениям.
dependentRequiredВ более новых версиях спецификации JSON Schema (2019-09 и выше), в
Ajv применяется dependentRequired, заменяющий списочные
зависимости.
const schema = {
type: "object",
properties: {
username: { type: "string" },
password: { type: "string" },
otp: { type: "string" }
},
dependentRequired: {
password: ["username"]
}
};
Механизм работает строго симметрично: если присутствует
password, обязательно должен присутствовать
username. Это упрощённая и более читаемая форма
классического dependencies.
Особенность dependentRequired заключается в том, что он
не накладывает ограничений на значение — только на факт присутствия
свойств.
dependentSchemasdependentSchemas расширяет идею зависимостей, позволяя
применять целую схему в зависимости от наличия свойства.
const schema = {
type: "object",
properties: {
paymentMethod: { type: "string" },
cardNumber: { type: "string" },
paypalEmail: { type: "string" }
},
dependentSchemas: {
paymentMethod: {
if: {
properties: { paymentMethod: { const: "card" } }
},
then: {
required: ["cardNumber"]
},
else: {
required: ["paypalEmail"]
}
}
}
};
В данном примере поведение объекта зависит от значения
paymentMethod, а не только от его наличия. Это позволяет
строить многоуровневую логику валидации без необходимости писать
императивные проверки.
if / then / elseХотя if / then / else не является частью
dependencies, на практике он часто используется для
реализации более гибких зависимостей между свойствами.
const schema = {
type: "object",
properties: {
accountType: { type: "string" },
companyName: { type: "string" },
personalId: { type: "string" }
},
if: {
properties: { accountType: { const: "business" } }
},
then: {
required: ["companyName"]
},
else: {
required: ["personalId"]
}
};
Такая конструкция позволяет моделировать взаимоисключающие сценарии, где структура объекта динамически изменяется в зависимости от контекста.
В реальных схемах Ajv часто используется комбинация различных типов зависимостей, что позволяет описывать сложные правила без дублирования логики.
const schema = {
type: "object",
properties: {
method: { type: "string" },
token: { type: "string" },
apiKey: { type: "string" },
signature: { type: "string" }
},
dependentRequired: {
token: ["signature"]
},
dependentSchemas: {
apiKey: {
required: ["method"]
}
}
};
Здесь одновременно применяются требования к наличию полей и схемные ограничения, что позволяет формировать многоуровневую систему валидации.
При компиляции схемы Ajv трансформирует зависимости в оптимизированные проверки. Это влияет на производительность:
Порядок применения правил определяется структурой схемы, а не порядком описания свойств.
При проектировании схем важно учитывать возможные конфликты:
required и dependentRequired
может приводить к избыточным условиям;dependencies и
if/then/else требует аккуратной логической структуры;При чрезмерной вложенности зависимостей схема становится трудно анализируемой, хотя Ajv продолжает корректно её исполнять.
Зависимости между свойствами фактически формируют декларативную систему правил, в которой объект рассматривается как набор взаимосвязанных условий. Такой подход позволяет описывать:
Использование зависимостей в Ajv делает возможным перенос сложной логики проверки данных из кода приложения непосредственно в схему валидации.