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

如何从OpenAPI规范或TypeScript类型自动生成React表单?

基于OpenAPI规范或TypeScript类型自动生成React表单的方案

当然可以实现,下面分两种路径给出具体解决方案:

一、基于FastAPI生成的OpenAPI规范(openapi.json)生成表单

1. 修复react-jsonschema-form的使用问题

你之前用react-jsonschema-form(简称RJSF)无法正常工作,大概率是没有正确将OpenAPI规范转换为兼容的JSON Schema,或者加载文件的方式有误:

  • OpenAPI的Schema定义和标准JSON Schema有细微差异,需要用openapi-schema-to-json-schema工具转换
  • 加载openapi.json时,不要直接读取本地文件路径,而是通过HTTP请求获取(比如FastAPI默认提供的/openapi.json接口)

示例代码:

import { Form } from '@rjsf/core';
import { convert } from 'openapi-schema-to-json-schema';
import { useEffect, useState } from 'react';

export function MessageForm() {
  const [schema, setSchema] = useState(null);

  useEffect(() => {
    // 从FastAPI获取openapi规范
    fetch('/openapi.json')
      .then(res => res.json())
      .then(openapi => {
        // 提取Message的schema并转换为JSON Schema
        const messageOpenApiSchema = openapi.components.schemas.Message;
        const jsonSchema = convert(messageOpenApiSchema);
        setSchema(jsonSchema);
      });
  }, []);

  if (!schema) return <div>Loading...</div>;

  return <Form schema={schema} onSubmit={({ formData }) => console.log(formData)} />;
}

2. 直接使用OpenAPI专用表单生成工具

还有更省心的工具,比如openapi-react-form,它可以直接解析OpenAPI规范并生成表单,无需手动转换Schema:

import { OpenApiForm } from 'openapi-react-form';
import { useEffect, useState } from 'react';

export function MessageForm() {
  const [openapi, setOpenapi] = useState(null);

  useEffect(() => {
    fetch('/openapi.json').then(res => res.json()).then(setOpenapi);
  }, []);

  if (!openapi) return <div>Loading...</div>;

  return (
    <OpenApiForm
      openapi={openapi}
      schemaName="Message"
      onSubmit={values => console.log(values)}
    />
  );
}

二、基于生成的TypeScript类型生成表单

如果你更倾向于用已有的TypeScript类型(比如自动生成的Message类型),可以通过类型转Schema的方式结合表单库实现:

1. 结合Zod + React Hook Form

先把TypeScript类型转换为Zod Schema,再用React Hook Form做表单渲染,类型完全同步:

  • 第一步,用ts-to-zod工具把TypeScript类型转成Zod Schema:
    安装依赖:npm install ts-to-zod --save-dev
    创建脚本generate-zod.ts:

    import { generateSchema } from 'ts-to-zod';
    import fs from 'fs';
    
    const tsCode = `export type Message = { role: string; content: string; };`;
    const { zodSchema } = generateSchema(tsCode, 'Message');
    
    fs.writeFileSync('./src/schemas/message.zod.ts', zodSchema);
    

    运行脚本生成Zod Schema文件。

  • 第二步,在React组件中使用:

    import { useForm } from 'react-hook-form';
    import { zodResolver } from '@hookform/resolvers/zod';
    import { z } from 'zod';
    import { MessageSchema } from './schemas/message.zod';
    
    type Message = z.infer<typeof MessageSchema>;
    
    export function MessageForm() {
      const { register, handleSubmit, formState: { errors } } = useForm<Message>({
        resolver: zodResolver(MessageSchema)
      });
    
      const onSubmit = (data: Message) => console.log(data);
    
      return (
        <form onSubmit={handleSubmit(onSubmit)}>
          <div>
            <label>Role:</label>
            <input {...register('role')} />
            {errors.role && <p>{errors.role.message}</p>}
          </div>
          <div>
            <label>Content:</label>
            <textarea {...register('content')} />
            {errors.content && <p>{errors.content.message}</p>}
          </div>
          <button type="submit">Submit</button>
        </form>
      );
    }
    

2. 使用Formily直接解析TypeScript类型

Formily支持直接从TypeScript类型生成表单,无需手动转换Schema:
安装依赖:npm install @formily/core @formily/react @formily/ts-transformer --save
示例代码:

import { createForm } from '@formily/core';
import { FormProvider, FormField, Input, Textarea } from '@formily/react';
import { transformSchema } from '@formily/ts-transformer';

// 从TypeScript类型生成表单Schema
const formSchema = transformSchema<{
  role: string;
  content: string;
}>();

export function MessageForm() {
  const form = createForm({
    initialValues: { role: '', content: '' },
    onSubmit: (values) => console.log(values)
  });

  return (
    <FormProvider form={form}>
      <FormField schema={formSchema['role']} component={Input} />
      <FormField schema={formSchema['content']} component={Textarea} />
      <button type="submit" onClick={() => form.submit()}>Submit</button>
    </FormProvider>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 07:10:09