AJV 验证器和自定义或用户友好的错误消息

标签 ajv

我有以下架构和 json 来使用 ajv 进行验证。我正在开发一个 REST API,它采用 JSON 并根据模式进行验证,并返回错误(400- 带有 ajv 错误)或(200 - 成功验证时)

const schema = {
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": [ "countries" ],
  "definitions": {
    "europeDef": {
      "type": "object",
      "required": ["type"],
      "properties": { "type": {"const": "europe"} }
    },
    "asiaDef": {
      "type": "object",
      "required": ["type"],
      "properties": { "type": {"const": "asia"} }
    }
  },
  "properties": {
    "countries": {
      "type": "array",
      "items": {
        "oneOf":[
          { "$ref": "#/definitions/europeDef" },
          { "$ref": "#/definitions/asiaDef"}
        ]
      }
    }
  }
}
const data = {
  "countries":[
    {"type": "asia1"},
    {"type": "europe1"}
  ]
}
const isValid = ajv.validate(schema, data); //schema, data
if(! isValid){
  console.log(ajv.errors);
}

错误是:

[ { keyword: 'const',
    dataPath: '/countries/0/type',
    schemaPath: '#/definitions/europeDef/properties/type/const',
    params: { allowedValue: 'europe' },
    message: 'should be equal to constant' },
  { keyword: 'const',
    dataPath: '/countries/0/type',
    schemaPath: '#/definitions/asiaDef/properties/type/const',
    params: { allowedValue: 'asia' },
    message: 'should be equal to constant' },
  { keyword: 'oneOf',
    dataPath: '/countries/0',
    schemaPath: '#/properties/countries/items/oneOf',
    params: { passingSchemas: null },
    message: 'should match exactly one schema in oneOf' },
  { keyword: 'const',
    dataPath: '/countries/1/type',
    schemaPath: '#/definitions/europeDef/properties/type/const',
    params: { allowedValue: 'europe' },
    message: 'should be equal to constant' },
  { keyword: 'const',
    dataPath: '/countries/1/type',
    schemaPath: '#/definitions/asiaDef/properties/type/const',
    params: { allowedValue: 'asia' },
    message: 'should be equal to constant' },
  { keyword: 'oneOf',
    dataPath: '/countries/1',
    schemaPath: '#/properties/countries/items/oneOf',
    params: { passingSchemas: null },
    message: 'should match exactly one schema in oneOf' } ]

我知道为什么会出现错误(原因:因为我使用了 'asia1' & 'europe1' 并且它不符合模式标准)

我的问题是,因为我已经导出了这个模式,所以我几乎可以理解这个错误。但是对于第三者来说,肯定需要一些时间来弄清楚(如果模式/错误更复杂,可能需要更多时间)。

如果我按原样返回整个错误消息作为响应,那么理解和呈现给最终用户的错误消息将更加复杂。

那么,有什么方法可以提供更有意义且用户友好的错误消息以供理解吗? 例如:在 JSON 中找到无效的国家/地区值

我检查过:ajv-errors、better-ajv-errors 但它们没有提供我想要的确切方式?

有人可以建议如何以更用户友好的方式或任何替代机制来做到这一点吗?

最佳答案

我正在使用下面的代码来生成人类可读的错误消息

let msg: string = "Wrong body" // fallback error message;
if (errors && errors.length > 0) {
  const error = errors[0];
  msg = `${error.instancePath} ${error.message}`;
}
res.status(4xx).json({
  errorMsg: msg,
});

我使用以下依赖项在运行时使用以下代码生成验证函数

"dependencies": {
  "ajv": "^8.11.0",
  ... // other dependencies
}
"devDependencies": {
  "ajv-cli": "^5.0.0"
}

下面的代码在项目构建之前运行,因此创建了运行时生成的验证文件

const ajv = new Ajv({
  schemas: schemas, // list of parsed json *.json schemas
  code: { source: true, esm: true },
});
let moduleCode = standaloneCode(ajv);

下面是显示错误信息的几个例子

  1. 属性(property)丢失案例: “/items/0/price 必须具有必需的属性‘currency_code’”
  2. 附加属性的大小写:“/address 不能有附加属性”
  3. 数量为小数的情况(允许为+ve数):"/items/0/quantity must be integer"
  4. 数量为-ve的情况(允许为+ve数):"/items/0/quantity must be >= 1"
  5. 不允许传递值的情况(枚举的情况):/items/0/price/currency_code 必须等于允许的值之一

关于AJV 验证器和自定义或用户友好的错误消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59544941/

相关文章:

jsonschema - 在 anyOf 中为 JSON Schema 嵌套 oneOf

json - $ref 不适用于数组类型 json 模式

node.js - 我可以使用 ajv json 模式验证日期,而不将日期转换为字符串吗?

javascript - 是否可以从另一个 AJV 定义中引用枚举中的属性名称?

typescript - 类验证器的高级条件(可能)?

javascript - 最新的 AJV 和 ajv-formats 必须在 React 中被破坏

javascript - 如何通过语句静态验证 JS 构造语句

javascript - fastify 和 ajv 模式验证

javascript - 使用 AJV 解析无效对象的自定义架构