You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 };

关键逻辑说明

  1. 经纬度组联动:通过when判断,只要其中一个经纬度字段存在,另一个就必须必填,避免出现只填单一经纬度的情况。
  2. 地址字段组联动:同样用when做条件判断,当任意两个地址字段存在时,第三个字段必须必填,保证地址信息的完整性。
  3. 二选一规则:
    • .or('Longitude', 'AddressLine'):确保至少有一组信息被提供,不能两组都为空
    • .oxor('Longitude', 'AddressLine'):确保两组信息不能同时存在,严格实现二选一要求
  4. .unknown(true):兼容Address对象中未定义的字段(如County),不对其做校验。

内容的提问来源于stack exchange,提问作者Shanu k k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 16:42:21