JOI验证程序替代架构错误消息

时间:2020-04-27 07:03:59

标签: javascript node.js hapijs joi

我就像尝试使用Joi.alternatives.try()创建Joi模式一样。这是我尝试过的模式。

Joi.alternatives().try(Joi.object({
    type: Joi.number().required().label('Error1!!')
}), Joi.object({
    reason: Joi.string().required().label('Error2!!')
})).label('Error!!')

这是我使用过的对象。

{ reason: 2 }

我期望错误为Error2!!或包含字符串Error2!!的错误。但是我收到错误消息

Validation Error: "Error!!" does not match any of the allowed types

此错误来自父节点。

如何使错误特定于对象?也就是说,错误来自替代对象节点而不是父对象。

您可以使用this平台在线验证架构。

更新: 这是我使用的示例架构。

employee_retired = Joi.object({
    type: Joi.number().required().valid(2, 3, 7),
    reason: Joi.string().required()
        .min(1)
        .max(100),
    firstname: Joi.string()
        .required(),
    lastname: Joi.string()
        .required()
        .min(1)
        .max(255),
    personaldetails: Joi.alternatives().conditional('type', {
        is: 2, then: Joi.array().items(Joi.object({
            address: Joi.string().required()
                .min(1)
                .max(100),
            salary: Joi.string().required()
                .min(0)
                .max(500),
            contactnumbers: Joi.array().items(Joi.object({
                mobile: Joi.string().required()
                    .min(0)
                    .max(15),
                home: Joi.string()
                    .required()
                    .min(1)
                    .max(15),
            })).max(50).required(),
        }).required()).max(50).required(),
        otherwise: Joi.forbidden(),
    }),
    monthlysavings: Joi.alternatives().conditional('type', {
            is: 3,
            then: Joi.number()
                .required()
                .min(0)
                .max(50000),
            otherwise: Joi.forbidden(),
        }),
    isapproved: Joi.boolean().required(),
});

empolyee_working = Joi.object({
    type: Joi.number().required().valid(2, 3, 7),
    reason: Joi.string().required()
        .min(1)
        .max(100),
    firstname: Joi.string()
        .required(),
    lastname: Joi.string()
        .required()
        .min(1)
        .max(255),
    contactnumbers: Joi.array().items(Joi.object({
        mobile: Joi.string().required()
            .min(0)
            .max(15),
        home: Joi.string()
            .required()
            .min(1)
            .max(15),
    })).max(50).required(),
    monthlysavings: Joi.alternatives().conditional('type', {
        is: 3,
        then: Joi.number().required()
            .min(1)
            .max(50000),
        otherwise: Joi.forbidden(),
    }),
    isapproved: Joi.boolean().required(),
})

const employee = Joi.alternatives().try(employee_retired, empolyee_working);

1 个答案:

答案 0 :(得分:2)

您可以使用object.or来解决此问题:

Joi.object({
    type: Joi.number().label('Error1!!'),
    reason: Joi.string().label('Error2!!')
}).or('type', 'reason').label('Error!!')

测试:

{}
// Validation Error: "Error!!" must contain at least one of [Error1!!, Error2!!]
{ reason: 2 }
// Validation Error: "Error2!!" must be a string
{ type: "a" } // note that due to default `convert` behavior, `{ type: "2" }` would pass
// Validation Error: "Error1!!" must be a number
{ a: "b" }
// Validation Error: "a" is not allowed. "Error!!" must contain at least one of [Error1!!, Error2!!]

更新(评论后)

确实有点冗长,但遵循相同的逻辑:

  • 退休的和在职的员工拥有相同的结构
  • 只有personaldetailscontactnumbers有所不同

因此,以下几行内容应为您提供精确的验证错误消息(尽管我没有测试所有情况)。我只是“合并”了两个员工声明,两个不同的案例personaldetailscontactnumbers不再声明为required,而是在最后的or中指定。

Joi.object({
    type: Joi.number().required().valid(2, 3, 7),
    reason: Joi.string().required()
        .min(1)
        .max(100),
    firstname: Joi.string()
        .required(),
    lastname: Joi.string()
        .required()
        .min(1)
        .max(255),
    personaldetails: Joi.alternatives().conditional('type', {
        is: 2, then: Joi.array().items(Joi.object({
            address: Joi.string().required()
                .min(1)
                .max(100),
            salary: Joi.string().required()
                .min(0)
                .max(500),
            contactnumbers: Joi.array().items(Joi.object({
                mobile: Joi.string().required()
                    .min(0)
                    .max(15),
                home: Joi.string()
                    .required()
                    .min(1)
                    .max(15),
            })).max(50).required(),
        // N.B.: no more .required() on the next line, .or() will handle it conditionally
        }).required()).max(50),
        otherwise: Joi.forbidden(),
    }),
    contactnumbers: Joi.array().items(Joi.object({
        mobile: Joi.string().required()
            .min(0)
            .max(15),
        home: Joi.string()
            .required()
            .min(1)
            .max(15),
    // N.B.: no more .required() on the next line, .or() will handle it conditionally
    })).max(50),
    monthlysavings: Joi.alternatives().conditional('type', {
            is: 3,
            then: Joi.number()
                .required()
                .min(0)
                .max(50000),
            otherwise: Joi.forbidden(),
        }),
    isapproved: Joi.boolean().required(),
}).or('personaldetails', 'contactnumbers').label('OR failure')
相关问题