json 模式中使用 AJV 的空值验证

Empty values validation in json schema using AJV

我正在使用 Ajv 验证我的 JSON 数据。我无法找到将空字符串验证为键值的方法。我尝试使用模式,但它没有抛出适当的消息。

这是我的架构

{
    "type": "object",
    "properties": {
        "user_name": { "type": "string" , "minLength": 1},
        "user_email": { "type": "string" , "minLength": 1},
        "user_contact": { "type": "string" , "minLength": 1}
    },
    "required": [ "user_name", 'user_email', 'user_contact']
}

我正在使用 minLength 检查值是否应包含至少一个字符。但它也允许空space。

目前 AJV 中没有这样做的内置选项。

你可以这样做:

ajv.addKeyword('isNotEmpty', {
  type: 'string',
  validate: function (schema, data) {
    return typeof data === 'string' && data.trim() !== ''
  },
  errors: false
})

并且在 json 架构中:

{
  [...]
  "type": "object",
  "properties": {
    "inputName": {
      "type": "string",
      "format": "url",
      "isNotEmpty": true,
      "errorMessage": {
        "isNotEmpty": "...",
        "format": "..."
      }
    }
  }
}

我找到了另一种方法,使用 "not" 关键字和 "maxLength":

{
  [...]
  "type": "object",
  "properties": {
    "inputName": {
      "type": "string",
      "allOf": [
        {"not": { "maxLength": 0 }, "errorMessage": "..."},
        {"minLength": 6, "errorMessage": "..."},
        {"maxLength": 100, "errorMessage": "..."},
        {"..."}
      ]
    },
  },
  "required": [...]
}

不幸的是,如果有人用 space 填写字段,它将有效,因为 space 算作字符。这就是为什么我更喜欢 ajv.addKeyword('isNotEmpty', ...) 方法,它可以在验证之前使用 trim() 函数。

干杯!

现在可以使用 ajv-keywords 来实现。
它是可用于 ajv 验证器的自定义模式的集合。

正在将架构更改为

{
  "type": "object",
  "properties": {
    "user_name": {
      "type": "string",
      "allOf": [
        {
          "transform": [
            "trim"
          ]
        },
        {
          "minLength": 1
        }
      ]
    },
   // other properties
  }
}

使用 ajv 关键字

const ajv = require('ajv');
const ajvKeywords = require('ajv-keywords');
const ajvInstance = new ajv(options);
ajvKeywords(ajvInstance, ['transform']);

transform 关键字指定在验证之前要执行的转换。

我做了与 Ronconi 所说的相同的事情,但想强调如何使用模式,例如“不检查逻辑”。

ajv.addKeyword({
    keyword: 'isNotEmpty',    
    validate: (schema , data) => {
        if (schema){
            return typeof data === 'string' && data.trim() !== ''
        }
        else return true;
    }
});

const schema = {
    type: "object",
    properties: {
        fname: {
            description: "first name of the user",
            type: "string",
            minLength: 3,
            isNotEmpty: false,
        },
}

基于@arthur-ronconi answer, here is another solution that works in Typescript, using the latest version of Ajv (documentation):

import Ajv, { _, KeywordCxt } from "ajv/dist/jtd";

const ajv = new Ajv({ removeAdditional: "all", strictRequired: true });
ajv.addKeyword({
  keyword: 'isNotEmpty',
  schemaType: 'boolean',
  type: 'string',
  code(cxt: KeywordCxt) {
    const {data, schema} = cxt;
    if (schema) {
      cxt.fail(_`${data}.trim() === ''`);
    }
  },
  error: {
    message: 'string field must be non-empty'
  }
});