Joi验证需求:经纬度与地址字段二选一校验
正确的Joi地址二选一验证实现方案
需求说明
我需要对如下结构的Address对象做Joi验证:
"Address": { "Id": "", "AddressLine": "lll", "City": "nbn", "PostalCode": "201321", "County": "", "Longitude": "", "Latitude": "" }
验证规则要求必须二选一:
- 要么同时提供有效的
Latitude(纬度)和Longitude(经度) - 要么同时提供有效的
AddressLine(地址行)、City(城市)和PostalCode(邮政编码)
如果经纬度为空或缺失,则必须验证地址字段的有效性,反之亦然。之前尝试的代码未达到预期效果,求正确实现方案。
正确实现代码
const Joi = require("joi"); const dataSchema = Joi.object({ Id: Joi.string().required().label("Task ID"), Address: Joi.object({ // 经纬度联动:填一个就必须填另一个 Longitude: Joi.number().when('Latitude', { is: Joi.exist(), then: Joi.required().label("Longitude"), otherwise: Joi.optional() }), Latitude: Joi.number().when('Longitude', { is: Joi.exist(), then: Joi.required().label("Latitude"), otherwise: Joi.optional() }), // 地址字段联动:填任意两个就必须填第三个 AddressLine: Joi.string().when(Joi.object({ City: Joi.exist(), PostalCode: Joi.exist() }), { is: Joi.valid(true), then: Joi.required().label("AddressLine"), otherwise: Joi.optional() }), City: Joi.string().when(Joi.object({ AddressLine: Joi.exist(), PostalCode: Joi.exist() }), { is: Joi.valid(true), then: Joi.required().label("City"), otherwise: Joi.optional() }), PostalCode: Joi.string().when(Joi.object({ AddressLine: Joi.exist(), City: Joi.exist() }), { is: Joi.valid(true), then: Joi.required().label("PostalCode"), otherwise: Joi.optional() }) }) // 强制二选一:至少选一组,且只能选一组 .or('Longitude', 'AddressLine') .oxor('Longitude', 'AddressLine') .unknown(true) }).unknown(true); function validateData(data) { return dataSchema.validate(data); } module.exports = { validateData };
关键逻辑说明
- 经纬度组联动:通过
when判断,只要其中一个经纬度字段存在,另一个就必须必填,避免出现只填单一经纬度的情况。 - 地址字段组联动:同样用
when做条件判断,当任意两个地址字段存在时,第三个字段必须必填,保证地址信息的完整性。 - 二选一规则:
.or('Longitude', 'AddressLine'):确保至少有一组信息被提供,不能两组都为空.oxor('Longitude', 'AddressLine'):确保两组信息不能同时存在,严格实现二选一要求
.unknown(true):兼容Address对象中未定义的字段(如County),不对其做校验。
内容的提问来源于stack exchange,提问作者Shanu k k
相关产品推荐
相关产品推荐

