【问题标题】:Joi validator alternative schema error messageJoi 验证器替代模式错误消息
【发布时间】:2020-08-10 16:19:36
【问题描述】:

我试图使用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);

【问题讨论】:

    标签: javascript node.js hapijs joi


    【解决方案1】:

    您可以使用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')
    

    【讨论】:

    • 嗨@Stock Overflaw,感谢您的回复。我尝试了您的解决方案,并且似乎在该场景中工作。但问题是,我在问题中提到的两个对象并不像带有简单键的对象那么简单。这些对象可能有多个键,其中可能是另一个对象或数组。这就是我选择替代品的原因。我将更新我需要的问题中的示例对象。我已对您的回复表示赞成。抱歉回复晚了。
    • 嗨@Nitheesh 我刚刚根据您展示的“真实”案例更新了答案。希望这可以帮助! :)
    猜你喜欢
    • 2014-11-15
    • 2019-04-28
    • 1970-01-01
    • 2020-05-08
    • 1970-01-01
    • 2020-09-13
    • 2018-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多