使用 ajv json 模式验证器的用户友好错误消息

use*_*984 8 jsonschema json-schema-validator ajv

假设我有架构和 JSON:

JSON 架构:

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"}
        ]
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

JSON:

const data = {
  "countries":[
    {"type": "asia1"},
    {"type": "europe1"}
  ]
}
Run Code Online (Sandbox Code Playgroud)
const isValid = ajv.validate(schema, data); //schema, data
if(! isValid){
  console.log(ajv.errors);
}
Run Code Online (Sandbox Code Playgroud)

和错误消息:

[ { 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' } ]
Run Code Online (Sandbox Code Playgroud)

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

有什么办法可以让它更加人性化吗?

Gag*_*gan 7

如果您需要 API,那么@apideck/better-ajv-errors很简单,并且输出更易读的错误消息。

这是一个例子:

import Ajv from 'ajv';
import { betterAjvErrors } from '@apideck/better-ajv-errors';

// Without allErrors: true, ajv will only return the first error
const ajv = new Ajv({ allErrors: true });

const schema = {
  type: "object",
  properties: {
    foo: {type: "integer"},
    bar: {type: "string"}
  },
  required: ["foo"],
  additionalProperties: false,
}

const data = {
  foo: "I don't know integer",
  bar: "abc"
}

const validate = ajv.compile(schema)
const valid = validate(data)

if (!valid) {
  console.log('Errors from ajv:\n', JSON.stringify(validate.errors, null, 2));
  const betterErrors = betterAjvErrors({ schema, data, errors: validate.errors });
  console.log('Errors from betterAjvErrors:\n', JSON.stringify(betterErrors, null, 2));
}

Run Code Online (Sandbox Code Playgroud)

这是输出:

Errors from ajv:
 [
  {
    "instancePath": "/foo",
    "schemaPath": "#/properties/foo/type",
    "keyword": "type",
    "params": {
      "type": "integer"
    },
    "message": "must be integer"
  }
]
Errors from betterAjvErrors:
 [
  {
    "message": "'foo' property type must be integer",
    "path": "{base}.foo",
    "context": {
      "errorType": "type"
    }
  }
]

Run Code Online (Sandbox Code Playgroud)


Man*_*lon 5

您可以使用扩展来自定义消息ajv-errors,以便您编写更好的消息(或应用 I18N 逻辑的键)。

它将显示您设置的内容errorMessage

const Ajv = require('ajv')
const AjvErrors = require('ajv-errors')

const ajv = new Ajv({ allErrors: true, jsonPointers: true })
AjvErrors(ajv)

const isValid = ajv.validate(yourSchema(), {
  countries: [
    { type: 'asia1' },
    { type: 'europe1' }
  ]
})
console.log(isValid)

if (!isValid) {
  console.log(ajv.errors)
}
function yourSchema () {
  return {
    $schema: 'http://json-schema.org/draft-07/schema#',
    type: 'object',
    required: ['countries'],
    definitions: {
      europeDef: {
        type: 'object',
        required: ['type'],
        properties: { type: { const: 'europe' } },
        errorMessage: 'it must be europe'
      },
      asiaDef: {
        type: 'object',
        required: ['type'],
        properties: { type: { const: 'asia' } },
        errorMessage: 'it must be asia'
      }
    },
    properties: {
      countries: {
        type: 'array',
        errorMessage: 'should be one of asia or europe',
        items: {
          oneOf: [
            { $ref: '#/definitions/europeDef' },
            { $ref: '#/definitions/asiaDef' }
          ]
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


Jak*_*kob 5

另请参阅其他库better-ajv-errors以显示带有上下文的详细错误消息。该库需要重新处理模式和数据:

const valid = validate(data);

if (!valid) {
  const output = betterAjvErrors(schema, data, validate.errors);
  console.log(output);
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述