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

如何用Zod根据page字段验证不同结构的form数组对象?

使用Zod根据page字段校验不同结构的form数组

你需要针对page字段的不同取值("A"或"B"),对form数组做严格的固定顺序+固定结构校验,核心是用Zod的tuple()替代array()来强制数组的每一项必须匹配指定的结构和顺序,同时为每个问答项固定question的字面量值,确保问答对一一对应。

完整实现代码

import { z } from "zod";

// Page A对应的单个问答项Schema
const pageAQuestion1 = z.object({
  question: z.literal("Basic Info"),
  answer: z.object({
    "Name": z.string(),
    "Organization or Affiliation (if applicable)": z.string()
  })
});

const pageAQuestion2 = z.object({
  question: z.literal("I am applying as a ..."),
  answer: z.array(z.string())
});

// Page B对应的单个问答项Schema
const pageBQuestion1 = z.object({
  question: z.literal("Please provide details of your enquiry or feedback below."),
  answer: z.string()
});

const pageBQuestion2 = z.object({
  question: z.literal("What is your preferred contact method?"),
  answer: z.object({
    "Telegram": z.string(),
    "Email": z.string()
  })
});

const pageBQuestion3 = z.object({
  question: z.literal("Please provide contact details for your preferred contact method"),
  answer: z.string()
});

// 最终的区分联合Schema
const contactSchema = z.discriminatedUnion("page", [
  z.object({
    page: z.literal("A"),
    // 用tuple强制数组的顺序和每一项的结构,array()会允许任意顺序/重复项
    form: z.tuple([pageAQuestion1, pageAQuestion2])
  }),
  z.object({
    page: z.literal("B"),
    form: z.tuple([pageBQuestion1, pageBQuestion2, pageBQuestion3])
  })
]);

// 测试示例(符合校验)
const validPageA = {
  "page":"A",
  "form":[
    {
      "question":"Basic Info",
      "answer":{
        "Name":"Basic name",
        "Organization or Affiliation (if applicable)":"Big company"
      }
    },
    {
      "question":"I am applying as a ...",
      "answer":[
        "Curator",
        "Service Provider"
      ]
    }
  ]
};

contactSchema.parse(validPageA); // 校验通过

// 测试错误示例(page A的form顺序颠倒)
const invalidPageA = {
  "page":"A",
  "form":[
    {
      "question":"I am applying as a ...",
      "answer":["Curator"]
    },
    {
      "question":"Basic Info",
      "answer":{"Name":"Test"}
    }
  ]
};

contactSchema.parse(invalidPageA); // 抛出校验错误

关键说明

  • 用z.tuple()替代z.array():普通的array()只会校验数组内的每一项是否符合某个通用schema,但无法强制数组的长度、顺序和每一项的专属结构。tuple()可以精确指定数组第n项必须匹配的schema,完全满足你的强制校验需求。
  • 固定question字面量:每个问答项的question字段用z.literal()固定为指定字符串,确保不会出现错误的问答匹配。
  • 区分联合(discriminatedUnion):通过page字段自动匹配对应的form校验规则,Zod会根据page的值选择对应的分支进行校验,性能和可读性都更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:48:11