带有完美消息的JSON模式验证

时间:2017-11-23 08:59:29

标签: validation json-schema-validator ajv

我将REST调用中的数据条目分为4个部分。可以通过以下方式将数据发送到REST调用: -

  1. 标题
  2. 查询参数
  3. path params
  4. 请求正文
  5. 因此,为了验证上述4个部分中任何一个键的存在,我已经用这种格式创建了一个模式。因此,如果我必须验证查询参数中的任何内容,我将添加密钥'查询'然后在其中添加需要验证的字段

    const schema = {
       id: 'Users_login_post',
       type: 'object',
       additionalProperties: false,
       properties: {
         headers: {
         type: 'object',
         additionalProperties: false,
         properties: {
          Authorization: {
            type: 'string',
            minLength: 10,
            description: 'Bearer token of the user.',
            errorMessages: {
              type: 'should be a string',
              minLength: 'should be atleast of 23 length',
              required: 'should have Authorization'
            }
          }
         },
         required: ['Authorization']
       },
       path: {
        type: 'object',
        additionalProperties: false,
        properties: {
          orgId: {
            type: 'string',
            minLength: 23,
            maxLength: 36,
            description: 'OrgId Id of the Organization.',
            errorMessages: {
              type: 'should be a string',
              minLength: 'should be atleast of 23 length', // ---> B
              maxLength: 'should not be more than 36 length',
              required: 'should have OrgId'
            }
          }
        },
        required: ['orgId']
       }
     }
    };
    

    现在,在我的快速代码中,我创建了一个请求对象,以便我可以用这种格式测试JSON的有效性。

    router.get("/org/:orgId/abc", function(req, res){
       var request = { //---> A
           path: {
              orgId : req.params.orgId
           },
           headers: {
              Authorization : req.headers.Authorization
           }
       }
       const Ajv = require('ajv');
    
       const ajv = new Ajv({
         allErrors: true,
       });
    
       let result = ajv.validate(schema, request);
       console.log(ajv.errorsText());
    });
    

    使用 AjV 对我的架构验证上述请求对象(在A)

    我得到的输出看起来像这样:

    data/headers should have required property 'Authorization', data/params/orgId should NOT be shorter than 23 characters
    

    现在我有一系列问题:

    1. 为什么消息在数据/标题 data / params / orgId 中显示数据字,即使我的变量名称为请求(在A)
    2. 为什么不使用我的错误消息,就像我提到的 orgId 一样:应至少为23长度(在B处)作为消息,即使这样,消息也不应短于23个字符
    3. 如何显示请求/标题,而不是数据/标题
    4. 另外,我用来验证我的路径params,查询params,header params,body param的方法,这是正确的方法,如果不是,那么更好的方法是做什么呢?

      请说清楚。

      提前致谢。

2 个答案:

答案 0 :(得分:1)

使用 ajv 关键字

import Ajv from 'ajv';
import AjvKeywords from 'ajv-keywords';
// ajv-errors needed for errorMessage
import AjvErrors from 'ajv-errors';

const ajv = new Ajv.default({ allErrors: true });

AjvKeywords(ajv, "regexp");
AjvErrors(ajv);

// modification of regex by requiring Z https://www.regextester.com/97766
const ISO8601UTCRegex = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?Z$/;

const typeISO8601UTC = {
  "type": "string",
  "regexp": ISO8601UTCRegex.toString(),
  "errorMessage": "must be string of format 1970-01-01T00:00:00Z. Got ${0}",
};

const schema = {
  type: "object",
  properties: {
    foo: { type: "number", minimum: 0 },
    timestamp: typeISO8601UTC,
  },
  required: ["foo", "timestamp"],
  additionalProperties: false,
};

const validate = ajv.compile(schema);

const data = { foo: 1, timestamp: "2020-01-11T20:28:00" }

if (validate(data)) {
  console.log(JSON.stringify(data, null, 2));
} else {
  console.log(JSON.stringify(validate.errors, null, 2));
}

https://github.com/rofrol/ajv-regexp-errormessage-example

答案 1 :(得分:0)

AJV无法知道您传递给validate函数的变量的名称。

但是,您应该能够从errors数组中找出哪些路径失败了(以及为什么),然后从那里构造消息。

请参见https://ajv.js.org/#validation-errors

要在架构中使用自定义错误消息,您需要一个AJV插件:ajv-errors。

请参见https://github.com/epoberezkin/ajv-errors