AJV if-then-else 基于枚举的条件类型

AJV if-then-else conditional type based on enum

我搜索了在 AJV 架构中使用 if-then-else 的示例,但没有找到 属性 类型和所需列表根据另一个 [=31= 的值而变化的特定情况].

案例:

我需要升级 userSchema,这样如果 属性 role = superuser,那么 customer_id 既可以为 null,也不需要。

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'
}

经过多次试验,我发现诀窍是 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' } }
  }