如何用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
相关产品推荐
相关产品推荐

