简体   繁体   中英

How to get property name from ajv output to map validation errors to human friendly messages?

I am using AJV library https://github.com/ajv-validator/ajv to validate the input of my nodejs express api. However, im having trouble extracting the property name in question for each error object in the returned array.

[{
  instancePath: '',
  schemaPath: '#/required',
  keyword: 'required',
  params: { missingProperty: 'start_date' },
  message: "must have required property 'start_date'"
}
{
  instancePath: '/top',
  schemaPath: '#/properties/top/type',
  keyword: 'type',
  params: { type: 'number' },
  message: 'must be number'
}]

As you can see from the above output extracting the property name ( start_date, top ) for each is a little different, so im hoping there is an easy way to do that without having to parse depending on the error type (keyword).

Expectation

i expect to be able to create a error like below mapping the original array. To do that i need the message which is available in the above original output and the property name which is not available.

[
  {  property: "start_date", message: "must have required property 'start_date"}
  {  property: "top", message: "must be number" },
]

Code

export interface ILeaderboardQuery {
    rank: string;
    entity_types: string[];
    country?: string | undefined;
    region?: string | undefined;
    start_date: string;
    end_date: string;
    top?: number | undefined;
}

export const LeaderboardQuerySchema: JSONSchemaType<ILeaderboardQuery> = {
    type: "object",
    properties: {
        rank: { type: "string" },
        entity_types: {
            type: "array",
            items: {
                type: "string",
            },
        },
        country: { type: "string", nullable: true },
        region: { type: "string", nullable: true },
        start_date: { type: "string" },
        end_date: { type: "string" },
        top: { type: "number", nullable: true },
    },
    required: ["rank", "start_date", "end_date"],
    additionalProperties: false,
};

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

export const GetLeaderboardValidator = (req: Request, res: Response, next: NextFunction) => {
    const validate = ajv.compile<ILeaderboardQuery>(LeaderboardQuerySchema);

    for (const err of validate.errors as DefinedError[]) {
        console.log(err);
    }
};

ajv : ^8.6.2"

You can use the ajv-errors package if you don't mind adding extra non-JSON Schema lingo into your schema.

You can add an extra errorMessage to any schema. It can be set to either a string or an object. If set to an object its keys are set to rules and values set to error messages.

Hopefully this makes sense:

const Ajv = require('ajv');
const ajvErrors = require('ajv-errors');

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

const validate = ajv.compile({
  type: "object",
  required: ["foo"],
  additionalProperties: false,
  properties: {
    foo: {
      type: "number",
      errorMessage: "CUSTOM ERROR: foo must be a number"
    }
  },
  errorMessage: {
    type: "CUSTOM ERROR: not an object",
    required: "CUSTOM ERROR: missing required property foo",
    additionalProperties: "CUSTOM ERROR: cannot have other properties"
  }
});


validate("foo");
validate.errors;

/*
[
  {
    instancePath: '',
    schemaPath: '#/errorMessage',
    keyword: 'errorMessage',
    params: { errors: [Array] },
    message: 'CUSTOM ERROR: not an object'
  }
]
*/

validate({});
validate.errors;

/*
[
  {
    instancePath: '',
    schemaPath: '#/errorMessage',
    keyword: 'errorMessage',
    params: { errors: [Array] },
    message: 'CUSTOM ERROR: missing required property foo'
  }
]
*/

validate({foo: 1, bar: 2});
validate.errors;

/*
[
  {
    instancePath: '',
    schemaPath: '#/errorMessage',
    keyword: 'errorMessage',
    params: { errors: [Array] },
    message: 'CUSTOM ERROR: cannot have other properties'
  }
]
*/

validate({foo: "wat"});
validate.errors;

/*
[
  {
    instancePath: '/foo',
    schemaPath: '#/properties/foo/errorMessage',
    keyword: 'errorMessage',
    params: { errors: [Array] },
    message: 'CUSTOM ERROR: foo must be a number'
  }
]
*/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM