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

如何根据subject字段值在Zod中条件验证role字段?

解决Zod条件验证问题:仅当subject为1时验证role字段

你可以通过两种方式实现这个需求:

方法一:使用Union类型拆分场景

把schema拆分成两种情况的联合类型,分别处理subject为1和不为1的场景:

// 定义基础字段的schema(不含role)
const baseSchema = z.object({
  subject: z.number().default(0),
  gender: z.object({
    owner: z.number(),
    stranger: z.number().array().min(1),
  }),
  age: z.object({
    owner: z.number(),
    stranger: z.number().array().min(1),
  }),
});

// subject为1时,强制验证role的结构
const subject1Schema = baseSchema.extend({
  subject: z.literal(1),
  role: z.object({
    owner: z.number(),
    stranger: z.number(),
  }),
});

// subject不为1时,role可以是任意值(允许不存在则加.optional())
const otherSubjectSchema = baseSchema.extend({
  subject: z.number().not(z.literal(1)),
  role: z.unknown().optional(),
});

// 合并为最终schema
const schema = z.union([subject1Schema, otherSubjectSchema]);

方法二:在整个Object上使用refine

直接在根object上调用refine,这样就能访问所有字段,根据subject的值决定是否验证role:

const schema = z.object({
  subject: z.number().default(0),
  gender: z.object({
    owner: z.number(),
    stranger: z.number().array().min(1),
  }),
  age: z.object({
    owner: z.number(),
    stranger: z.number().array().min(1),
  }),
  role: z.unknown(), // 先允许role为任意类型
}).refine((data) => {
  // subject不为1时直接通过验证
  if (data.subject !== 1) return true;
  
  // subject为1时,验证role的结构
  const roleValidator = z.object({
    owner: z.number(),
    stranger: z.number(),
  });
  return roleValidator.safeParse(data.role).success;
}, {
  message: "当subject为1时,role必须包含数字类型的owner和stranger字段",
  path: ["role"], // 让错误提示指向role字段
});

为什么之前的refine没用?

你之前尝试的refine应该是单独给某个字段调用的,这种情况下只能访问当前字段的值,无法获取其他字段(比如subject)。只有在整个object schema上调用refine,才能拿到完整的data对象,从而实现跨字段的条件验证。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:53:19