在Joi验证中比较两个对象(例如,避免重复)

时间:2019-06-20 15:35:03

标签: joi

我正在使用Joi验证复杂的表单条目。该表格要求两个地址mainContactAddressseniorContactAddress。我想验证它们,以确保它们不是相同的地址。

每个地址都是这样的对象:

{
    "line1": "123 Some Street",
    "line2": "Some Town",
    "county": "Some County",
    "postcode": "123 ABC",
    "townCity": "City"
}

我最初尝试过:

Joi.ukAddress().invalid(Joi.ref('seniorContactAddress'))

({ukAddress()是我创建的自定义扩展名,它指定上述每个字段为必需的字符串。)

这不起作用,因为即使两个对象具有相同的字符串值,两个对象之间的相等性===比较也会返回false

我看不到Joi方法可以做到这一点。我希望能够序列化对象(例如类似Object.values(mainContactAddress).join(',')然后比较结果字符串),但是Joi.ref()仅给出了对该对象的引用,所以我不能调用直接针对它起作用。

关于如何实现此验证/比较的任何想法吗?

1 个答案:

答案 0 :(得分:0)

我最终为自己的扩展程序编写了一个自定义规则:

{
    // Enforce a unique address compared to the senior contact
    name: 'mainContact',
    validate(params, value, state, options) {
        // Format addresses into a comparable string,
        // making sure we sort them as the stored version
        // is in a different order to the form-submitted one.
        const serialize = address =>
            Object.values(address)
                .sort()
                .join(',');

        const seniorContactAddress = get(
            state.parent,
            'seniorContactAddress',
            []
        );

        if (serialize(seniorContactAddress) === serialize(value)) {
            return this.createError(
                'address.matchesSenior',
                { v: value },
                state,
                options
            );
        } else {
            return value;
        }
    }
}

这确实感觉像是一种反模式(例如,滥用state来查看Joi对象中的其他值),但是它确实满足了我的需要。