AJV условный тип if-then-else, основанный на перечислении

#javascript #typescript #ajv

#javascript #typescript #ajv

Вопрос:

Я искал примеры использования if-then-else в схемах AJV, но не нашел конкретного случая, когда тип свойства и требуемый список изменяются на основе значения другого свойства.

Случай:

Мне нужно обновить, userSchema чтобы свойство if role = superuser , то customer_id было одновременно обнуляемым и необязательным.

 const userSchema: Schema<UserItem> = {
  $schema: 'http://json-schema.org/draft-07/schema#',
  type: 'object',
  required: ['id', 'email', 'customer_id'],
  additionalProperties: false,
  properties: {
    id: {
      type: 'string',
      format: 'uuid'
    },
    email: {
      type: 'string',
      format: 'email'
    },
    customer_id: {
      type: 'string',
      format: 'uuid'
    },
    role: {
      anyOf: [
        { type: 'null' },
        { enum: Object.values(UserRole) }
      ]
    }
  }
}
  

Я пытался…

 const userSchemaNullableCustomerId: Schema<UserItem> = {
  ...userSchema,
  if: {
    properties: {
      role: { const: UserRole.Superuser }
    }
  },
  then: {
    properties: {
      customer_id: {
        anyOf: [
          { type: 'null' },
          { type: 'string', format: 'uuid' }
        ]
      }
    },
    not: {
      required: ['customer_id']
    }
  }
}
  

но он все еще жалуется на это data.customer_id should be string . Как это можно решить?

Следующее должно быть правдой:

 // Valid
{
    "id": "id",
    "email": "foo@bar.com",
    "role": "superuser",
    "customer_id": null
},
{
    "id": "id",
    "email": "foo@bar.com",
    "role": "superuser"
},
{
    "id": "id",
    "email": "foo@bar.com",
    "role": "null",
    "customer_id": 'some-uuid...'
},
{
    "id": "id",
    "email": "foo@bar.com",
    "role": "user",
    "customer_id": 'some-uuid...'
}

// Invalid
{
    "id": "id",
    "email": "foo@bar.com",
    "role": "user",
    "customer_id": null
},
{
    "id": "id",
    "email": "foo@bar.com",
    "role": "user"
},
{
    "id": "id",
    "email": "foo@bar.com",
    "role": "superuser",
    "customer_id": 'nonUuidString'
}
  

Ответ №1:

После долгих экспериментов я обнаружил, что хитрость заключается в том, что customer_id свойство должно быть инициализировано как пустое, а role свойство требует проверки зависимости.

 ...
  properties: {
    id: {
      type: 'string',
      format: 'uuid'
    },
    email: {
      type: 'string',
      format: 'email'
    }
    customer_id: {},
    role: {
      anyOf: [
        { type: 'null' },
        { enum: Object.values(UserRole) }
      ]
    }
  },
  if: {
    dependencies: { role: ['role'] },
    properties: { role: { const: UserRole.Superuser } }
  },
  then: {
    properties: { customer_id: { anyOf: [{ type: 'null' }, { type: 'string', format: 'uuid' }] } }
  },
  else: {
    properties: { customer_id: { type: 'string', format: 'uuid' } }
  }