为什么我的 json 架构让错误的值通过?

why my json schema let a wrong value pass?

我试图在请求 api 之前验证 json 对象,但我有一个问题,我的 user 应该看起来像

{
    "type": "student",
    "firstname": "jhon",
    "lastname": "DOE",
    "login": "jDOE",
    "pwd": "jdoepassword",
    "classes": []
}

或当老师

{
    "type": "teacher",
    "firstname": "teacher",
    "lastname": "TEACHER",
    "login": "tTEACHER",
    "pwd": "tTeacherpassword"
}

我正在尝试使用 ajv 模块,这是我的代码:

var Ajv = require('ajv');
const ajv = new Ajv({allErrors: true});
const schema = {
  $jsonSchema: {
    anyOf: [
      {
        properties: {
          _id: {
            bsonType: 'objectId'
          },
          type: {
            'enum': [
              'student'
            ],
            bsonType: 'string',
            description: 'as to be a student'
          },
          firstname: {
            bsonType: 'string',
            description: 'must be a string'
          },
          lastname: {
            bsonType: 'string',
            description: 'must be a string'
          },
          login: {
            bsonType: 'string',
            description: 'must be a string',
            pattern: '^(?!$).*'
          },
          pwd: {
            bsonType: 'string',
            description: 'must be a string'
          },
          classes: {
            bsonType: 'array',
            items: {
              bsonType: [
                'string'
              ],
              additionalProperties: false
            }
          }
        },
        required: [
          'type',
          'firstname',
          'lastname',
          'login',
          'pwd',
          'classes'
        ],
        additionalProperties: false
      },
      {
        properties: {
          _id: {
            bsonType: 'objectId'
          },
          type: {
            'enum': [
              'teacher'
            ],
            bsonType: 'string',
            description: 'as to be a teacher'
          },
          firstname: {
            bsonType: 'string',
            description: 'must be a string'
          },
          lastname: {
            bsonType: 'string',
            description: 'must be a string'
          },
          login: {
            bsonType: 'string',
            description: 'must be a string',
            pattern: '^(?!$).*'
          },
          pwd: {
            bsonType: 'string',
            description: 'must be a string'
          }
        },
        required: [
          'type',
          'firstname',
          'lastname',
          'login',
          'pwd'
        ],
        additionalProperties: false
      }
    ]
  }
};
const test = ajv.compile(schema);
/* I initiate my command line app here so argv contains all needed fields */ 
let user = {};
user.type = argv.type || 'student';
user.firstname = argv.firstname;
user.lastname = argv.name;
user.login = argv.login || argv.firstname.slice(0, 1) + argv.name.slice(0, 7);
user.pwd = argv.password;
if (user.type == "student") user.classes = [];
const isValid = test(user);
if (isValid) {
    /* request API */
}

但是当我创建一个用户时

{
  type: 'fujkdswghldfkj',   /*<= here's the important part*/
  firstname: 'arandomfirstname',
  lastname: 'arandomlasname',
  login: 'arandomlogin',
  pwd: 'password',
  classes: []
}

请求 api 就好像使用类型“fujkdswghldfkj”而不是枚举 'student' 或 'teacher' 是正常的,有人知道为什么吗?

我认为您的架构定义有误。当我将其更改为:

const schema = {
  type: 'object',
  properties: {
    type: {
      enum: ['teacher', 'student']
    },
    firstname: {
      type: 'string',
    },
    lastname: {
      type: 'string',
    },
    login: {
      type: 'string',
    },
    pwd: {
      type: 'string'
    },
  },
  required: [
    'type',
    'firstname',
    'lastname',
    'login',
    'pwd',
  ],
};

然后执行以下操作:

const test = ajv.compile(schema);
const isValid = test({
  type: 'fujkdswghldfkj',   
  firstname: 'arandomfirstname',
  lastname: 'arandomlasname',
  login: 'arandomlogin',
  pwd: 'password',
  classes: [],
});

我收到以下验证错误:

[
  {
    keyword: 'enum',
    dataPath: '.type',
    schemaPath: '#/properties/type/enum',
    params: { allowedValues: ["teacher", "student"] },
    message: 'should be equal to one of the allowed values'
  }
]