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

如何在Zod中遍历属性并获取其类型与配置信息?

Zod Schema 属性遍历与配置项检查方案

问题描述

给定以下Zod基础代码:

import { z } from 'zod'

const Post = z.object({
  title: z.string(),
})

const User = z.object({
  name: z.string(),
  email: z.string().optional(),
  posts: z.array(Post),
  loginCount: z.number().min(1)
})

需要遍历Schema的属性并检查属性配置项,实现类似如下逻辑:

for (const name in shape) {
  const prop = shape[name]

  if (prop.min != null) {
    console.log(`Has min ${prop.min}`)
  }
  if (prop.max != null) {
    console.log(`Has max ${prop.max}`);
  }
  if (prop.optional === true) {
    console.log(`Is optional`);
  }
  if (prop.type) {
    if (prop.type is array) {
      prop.type.forEach(item => {
        console.log(`Has array item type ${item.name}`)
      })
    } else if (prop.type is union) {
      // ... show union type names
    } else {
      // show basic type name
    }
  }
}

核心需求包括:

  • 获取每个Schema的键名
  • 获取属性允许的类型(用于数据库表结构生成等场景)
  • 自动生成文档
  • 其他元数据提取类需求

解决方案

Zod提供shape属性访问对象Schema的属性,但要获取类型约束、可选性等配置,需结合Zod内部的_def属性实现,以下是具体代码和说明:

1. 递归遍历与配置项检查实现

import { z, ZodType, ZodObject, ZodString, ZodNumber, ZodArray, ZodOptional, ZodUnion } from 'zod';

// 递归分析Schema的函数
function analyzeSchema(schema: ZodType, parentKey = '') {
  // 处理可选类型:先提取内部真实Schema
  if (schema instanceof ZodOptional) {
    console.log(`${parentKey}: 是可选属性`);
    analyzeSchema(schema.unwrap(), parentKey);
    return;
  }

  // 处理数组类型
  if (schema instanceof ZodArray) {
    console.log(`${parentKey}: 类型为数组`);
    analyzeSchema(schema.element, `${parentKey}[元素]`);
    return;
  }

  // 处理联合类型
  if (schema instanceof ZodUnion) {
    console.log(`${parentKey}: 类型为联合类型,包含以下子类型:`);
    schema.options.forEach((subSchema, index) => {
      analyzeSchema(subSchema, `${parentKey}[${index}]`);
    });
    return;
  }

  // 处理对象类型:递归遍历所有属性
  if (schema instanceof ZodObject) {
    Object.entries(schema.shape).forEach(([key, propSchema]) => {
      const currentKey = parentKey ? `${parentKey}.${key}` : key;
      analyzeSchema(propSchema, currentKey);
    });
    return;
  }

  // 处理基础类型(字符串、数字)
  if (schema instanceof ZodString) {
    console.log(`${parentKey}: 类型为字符串`);
    // 提取字符串约束(最小长度、最大长度等)
    schema._def.checks.forEach(check => {
      if (check.kind === 'min') console.log(`${parentKey}: 最小长度 ${check.value}`);
      if (check.kind === 'max') console.log(`${parentKey}: 最大长度 ${check.value}`);
    });
  } else if (schema instanceof ZodNumber) {
    console.log(`${parentKey}: 类型为数字`);
    // 提取数字约束(最小值、最大值等)
    schema._def.checks.forEach(check => {
      if (check.kind === 'min') console.log(`${parentKey}: 最小值 ${check.value}`);
      if (check.kind === 'max') console.log(`${parentKey}: 最大值 ${check.value}`);
    });
  }
}

// 调用函数分析User Schema
analyzeSchema(User);

2. 运行输出示例

执行上述代码后,控制台会输出:

name: 类型为字符串
email: 是可选属性
email: 类型为字符串
posts: 类型为数组
posts[元素].title: 类型为字符串
loginCount: 类型为数字
loginCount: 最小值 1

3. 扩展应用场景

  • 数据库表结构生成:在分析过程中,将Zod类型映射为数据库字段类型(如z.string()对应VARCHAR,z.number()对应INT),同时记录可选性、约束条件,自动生成建表SQL语句。
  • 文档生成:把分析结果整理成Markdown/HTML格式,包含字段名、类型、约束、可选性等信息,快速生成API或数据结构文档。

注意事项

  • _def是Zod的内部属性,虽目前稳定,但官方未承诺永久兼容。若需长期维护,建议通过Zod的refine方法或自定义类型扩展来封装元数据,避免直接依赖内部属性。
  • 对于枚举、日期、自定义校验类型等复杂场景,可在analyzeSchema函数中添加对应的instanceof判断分支,扩展处理逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 04:12:45