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

如何在Zod解析前将对象转换为数组?

解决Zod适配单个对象/数组混合返回的问题

问题场景

外部API端点的fields字段存在两种返回格式:

  • 字段数量为1时,返回单个对象:
{
  "fields": { "fullName": "fieldFullname", "type": "fieldType" }
}
  • 字段数量多于1时,返回对象数组:
{
  "fields": [
      { "fullName": "fieldFullname", "type": "fieldType" },
      { "fullName": "fieldFullname", "type": "fieldType" }
   ]
}

原Zod Schema仅支持数组类型,导致单个对象返回时抛出类型错误:

{
  "code": "invalid_type",
  "expected": "array",
  "received": "object",
  "path": [],
  "message": "Expected array, received object"
}

解决方案

可以通过Zod的preprocess或union+transform实现动态类型转换,将单个对象统一转为数组格式,同时完成验证。

方案一:使用preprocess预处理输入

export const metadataFieldSchema = z.object({
  fullName: z.string().optional(),
  type: z.string().optional(),
});

export const sObjectMetadataSchema = z.object({
  fields: z.preprocess(
    // 预处理:单个对象转数组,数组保持原样
    (input) => Array.isArray(input) ? input : [input],
    // 验证预处理后的值为metadataFieldSchema数组,支持可选
    z.array(metadataFieldSchema).optional()
  ),
});

方案二:使用union兼容两种类型+transform统一格式

export const metadataFieldSchema = z.object({
  fullName: z.string().optional(),
  type: z.string().optional(),
});

export const sObjectMetadataSchema = z.object({
  fields: z.union([
    metadataFieldSchema,
    z.array(metadataFieldSchema)
  ]).transform((value) => {
    // 统一转为数组格式
    return Array.isArray(value) ? value : [value];
  }).optional(),
});

原实现错误原因

之前的transform写法错误在于:回调函数返回了Zod Schema(z.array(metadataFieldSchema).optional()),而transform要求返回验证后的具体值,而非Schema本身。正确逻辑应该是先处理输入结构,再执行验证,或者先兼容两种输入类型再统一转换格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 07:30:54