在本文中,你将学习如何应用 ChatGPT API 构建一个将 JSON 对象转换为 Typescript interface 的 Web 利用

为什么你须要它?

许多网站为不同的场景提供 API

简略的解决方案是发送 JSON 并返回 Typescript 中的interface

你也能够应用 JSON-to-typescript 库来实现,但我将应用 ChatGPT 向你展现这一点,因为你晓得,我喜爱魔法(AI) ⭐️

帮帮我

我曾经创立了这个我的项目的残缺代码仓库,请随便克隆、应用它并给我一个 star 谢谢⭐️

https://github.com/zidanDirk/json-to-typescript-chatgpt-cn

什么是 ChatGPT ?

ChatGPT 是一种由 OpenAI 训练的 AI 语言模型,能够生成文本并以相似人类的对话形式与用户进行交互。用户能够在短短几秒钟内提交申请并取得信息或从宽泛的主题中取得问题的答案。

ChatGPT 还有助于编写、调试和解释代码片段。 值得一提的是,ChatGPT 及其 API 目前收费凋谢给公众应用。(因为家喻户晓的起因,ChatGPT 账号申请可能有些麻烦,然而我置信这肯定难不倒聪慧的你)

因而在本文中,咱们将应用它的 API 构建一个 JSON 到 Typescript 的转换器

我的项目设置

在这里,咱们会为 Web 利用创立我的项目环境。 咱们将在前端应用 React.js,在后端应用 Node.js

通过运行以下代码为 Web 利用创立我的项目文件夹:

mkdir json-to-typescript-cncd json-to-typescript-cn

设置 Node.js 服务端

进入 server 目录并创立一个 package.json 文件

mkdir servercd server & npm init -y

装置 Express, Nodemon , CORS, dotenv 包

npm install express cors nodemon dotenv

ExpressJS 是一个疾速、极简的框架,它提供了多种用于在 Node.js 中构建 Web 应用程序的性能; CORS 是一个容许不同域之间通信的 Node.js 包,而 Nodemon 是一个在检测到文件更改后主动重启服务器的 Node.js 工具。Dotenv 是一个零依赖模块,它将环境变量从 .env 文件加载到 process.env 中。

创立一个 index.js 文件作为 Web 服务器的入口

touch index.js

应用 Express.js 设置 Node.js 服务器。 当浏览器拜访 http://localhost:4000/api 时,上面的代码片段会返回一个 JSON 对象

//index.jsconst express = require("express");const cors = require("cors");const app = express();const PORT = 4000;app.use(express.urlencoded({ extended: true }));app.use(express.json());app.use(cors());app.get("/api", (req, res) => {    res.json({        message: "Hello world",    });});app.listen(PORT, () => {    console.log(`Node.js 服务正在监听 ${PORT} 端口 ...`);});

通过将 start 命令增加到 package.json 文件中的 scripts 列表来配置 Nodemon。 上面的代码片段应用 Nodemon 启动服务器。

//在 server/package.json 文件中"scripts": {    "test": "echo \"Error: no test specified\" && exit 1",    "start": "nodemon index.js"  },

祝贺! 你当初能够应用以下命令启动服务器。

npm start

设置 React 利用

通过终端导航到根目录并创立一个新的 React.js 我的项目

npm create vite@latest✔ Project name:  client✔ Select a framework: › React✔ Select a variant: › JavaScriptcd client npm i 

在 client 目录装置  Monaco Editor for React 和  React Copy to Clipboard 库

npm install @monaco-editor/react react-copy-to-clipboard

Monaco Editor for React 是一个非常简略的包,用于将代码编辑器增加到 React 应用程序,而 React Copy to Clipboard 包容许咱们通过单击按钮复制和粘贴内容

从 React 应用程序中删除多余的文件,并更新 App.jsx 文件以显示 “Hello World” ,如下所示。

function App() {    return (        <div>            <p>Hello World!</p>        </div>    );}export default App;

如下所示,更新 src/index.css 款式文件

@import url("<https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap>");* {    box-sizing: border-box;    margin: 0;    padding: 0;    font-family: "Space Grotesk", sans-serif;}.app {    width: 100%;    min-height: 100vh;}.loading {    display: flex;    align-items: center;    justify-content: center;    width: 100%;    height: 100vh;}.header__container {    width: 100%;    display: flex;    align-items: center;    height: 10vh;    background-color: #e0f2fe;}.header__right {    display: flex;    align-items: center;}.runBtn {    padding: 10px 5px;    width: 100px;    margin-right: 10px;    cursor: pointer;    border: none;    border-radius: 3px;    box-shadow: 0 0 1px 1px #e0e0ea;    background-color: #065f46;    outline: none;    color: #fff;}.header {    border: 1px solid #ddd;    padding: 10px 20px;    border: 1px solid #e8e2e2;    display: flex;    align-items: center;    justify-content: space-between;    flex: 0.5;    height: 100%;}.code__container {    display: flex;    height: 95vh;    width: 100%;    align-items: flex-start;}.minimap {    display: none;}.editor {    padding: 10px 0px;    width: 100%;}.code,.output {    width: 50vw;}.deleteIcon {    height: 25px;    color: #cf0a0a;    cursor: pointer;}.copyIcon {    height: 25px;    color: #3e54ac;    cursor: pointer;}

构建利用用户界面

在这里,咱们将为 JSON 到 Typescript 转换器创立用户界面,使用户可能在屏幕左侧增加 JSON 对象,并在屏幕右侧查看 Typescript 中的后果。

首先,在 client/src 文件夹中创立一个 icons 文件夹。 icons 文件夹将蕴含上图中的删除和复制图标

cd client/srcmkdir iconscd iconstouch Copy.jsx Delete.jsx

更新 Copy.jsx 文件以增加来自 Heroicons 的 SVG 图标

import React from "react";const Copy = () => {    return (        <svg            xmlns='<http://www.w3.org/2000/svg>'            viewBox='0 0 24 24'            fill='currentColor'            className='w-6 h-6 copyIcon'        >            <path d='M7.5 3.375c0-1.036.84-1.875 1.875-1.875h.375a3.75 3.75 0 013.75 3.75v1.875C13.5 8.161 14.34 9 15.375 9h1.875A3.75 3.75 0 0121 12.75v3.375C21 17.16 20.16 18 19.125 18h-9.75A1.875 1.875 0 017.5 16.125V3.375z' />            <path d='M15 5.25a5.23 5.23 0 00-1.279-3.434 9.768 9.768 0 016.963 6.963A5.23 5.23 0 0017.25 7.5h-1.875A.375.375 0 0115 7.125V5.25zM4.875 6H6v10.125A3.375 3.375 0 009.375 19.5H16.5v1.125c0 1.035-.84 1.875-1.875 1.875h-9.75A1.875 1.875 0 013 20.625V7.875C3 6.839 3.84 6 4.875 6z' />        </svg>    );};export default Copy;

将上面的代码复制到 Delete.jsx 文件中。 它为删除按钮出现一个 SVG 图标。

import React from "react";const Delete = () => {    return (        <svg            xmlns='<http://www.w3.org/2000/svg>'            viewBox='0 0 24 24'            fill='currentColor'            className='w-6 h-6 deleteIcon'        >            <path                fillRule='evenodd'                d='M16.5 4.478v.227a48.816 48.816 0 013.878.512.75.75 0 11-.256 1.478l-.209-.035-1.005 13.07a3 3 0 01-2.991 2.77H8.084a3 3 0 01-2.991-2.77L4.087 6.66l-.209.035a.75.75 0 01-.256-1.478A48.567 48.567 0 017.5 4.705v-.227c0-1.564 1.213-2.9 2.816-2.951a52.662 52.662 0 013.369 0c1.603.051 2.815 1.387 2.815 2.951zm-6.136-1.452a51.196 51.196 0 013.273 0C14.39 3.05 15 3.684 15 4.478v.113a49.488 49.488 0 00-6 0v-.113c0-.794.609-1.428 1.364-1.452zm-.355 5.945a.75.75 0 10-1.5.058l.347 9a.75.75 0 101.499-.058l-.346-9zm5.48.058a.75.75 0 10-1.498-.058l-.347 9a.75.75 0 001.5.058l.345-9z'                clipRule='evenodd'            />        </svg>    );};export default Delete;

更新 App.jsx 文件来渲染 header 元素,如下所示

import React from "react";import Delete from "./icons/Delete";import Copy from "./icons/Copy";const App = () => {    const handleSubmit = () => {        console.log("运行按钮点击");    };    return (        <main className='app'>            <header className='header__container'>                <div className='header'>                    <h3>JSON</h3>                    <div className='header__right'>                        <button className='runBtn' onClick={handleSubmit}>                            运行                        </button>                        <Delete />                    </div>                </div>                <div className='header'>                    <h3>Typescript</h3>                    <Copy />                </div>            </header>            <div className='code__container'></div>        </main>    );};export default App;

下面的代码片段显示了 Web 应用程序的 header 组件。 在接下来的局部中,我会阐明如何将 Monaco 代码编辑器增加到 React 应用程序

增加 Monaco 代码编辑器到 React

Monaco Editor 是一款驰名的基于 Web 技术的代码编辑器,为 VS Code 提供反对,它只须要一行集成即可反对多种编程语言。

咱们曾经在上一节中装置了库。 接下来,将其导入 App.jsx 文件,如下所示

import React, { useState } from "react";import Delete from "./icons/Delete";import Copy from "./icons/Copy";import Editor from "@monaco-editor/react";const App = () => {    const [value, setValue] = useState("");    const [output, setOutput] = useState("");    const handleSubmit = () => {        console.log("Run Button Clicked");    };    return (        <main className='app'>            <header className='header__container'>                <div className='header'>                    <h3>JSON</h3>                    <div className='header__right'>                        <button className='runBtn' onClick={handleSubmit}>                            RUN                        </button>                        <Delete />                    </div>                </div>                <div>                    <h3>Typescript</h3>                    <Copy />                </div>            </header>            <div className='code__container'>                <div className='code'>                    <Editor                        height='90vh'                        className='editor'                        defaultLanguage='json'                        defaultValue='{ }'                        value={value}                        onChange={(value) => setValue(value)}                    />                </div>                <div className='output'>                    <Editor                        height='90vh'                        className='editor'                        defaultLanguage='typescript'                        options={{                            domReadOnly: true,                            readOnly: true,                        }}                        defaultValue=''                        value={output}                        onChange={(value) => setOutput(value)}                    />                </div>            </div>        </main>    );};export default App;

从下面的代码片段中,我从 Monaco Editor 包中导入了 Editor 组件。 第一个编辑器组件承受诸如 heightvaluedefaultLanguageonChange 事件之类的 props 第二个编辑器组件承受与第一个雷同的 props,但有一个名为 options 的附加 props,因为它是只读的,因而会禁止用户编辑它的值

如何在 Node.js 中与 ChatGPT 进行通信

在本节中,你将学习如何通过 Node.js 服务器中的 API 与 ChatGPT 进行通信。 咱们会将用户提供的 JSON 代码发送到 API,以将代码转换为其等效的 Typescript。 要做到这一点:

通过运行以下代码装置 OpenAI API Node.js 库

npm install openai

在 此处 登录或创立 OpenAI 帐户

单击导航栏上的 Personal 并从菜单栏中抉择 View API Keys 以创立新的密钥。

将 API 密钥复制到计算机上平安的中央; 咱们很快就会用到它

通过将以下代码复制到 server/index.js 文件来配置 API。

const { Configuration, OpenAIApi } = require("openai");const dotenv = require('dotenv')dotenv.config()const GPT_API_KEY = process.env.GPT_API_KEYif (!GPT_API_KEY) {    console.log("请配置 ChatGPT API Key")    return}const configuration = new Configuration({    apiKey: GPT_API_KEY,});const openai = new OpenAIApi(configuration);

在 server 目录下创立 .env 文件, 将 GPT_API_KEY 的值替换为你的 API 密钥。

GPT_API_KEY="<你的 GPT API 密钥>"

在服务器上创立一个 POST 路由,它将承受来自前端的 JSON 代码并生成其等效的 Typescript

// server/index.js 文件中app.post("/convert", (req, res) => {    console.log(req.body);});

更新前端 App.jsx 文件中的 handleSubmit 函数,将用户输出的 JSON 对象发送到服务器上的 /convert 接口

const handleSubmit = () => {    fetch("http://localhost:4000/convert", {        method: "POST",        body: JSON.stringify({            value,        }),        headers: {            "Content-Type": "application/json",        },    })        .then((res) => res.json())        .then((data) => {            setOutput(data.response);        })        .catch((err) => console.error(err));};

更新 /convert 接口,如下所示

app.post("/convert", async (req, res) => {    // 解构 JSON 对象    let { value } = req.body;    // 向 ChatGPT 发问    const prompt = `Convert the JSON object into Typescript interfaces \n ${value} Please, I need the only the code, I don't need any explanations.`;    const completion = await openai.createChatCompletion({        model: "gpt-3.5-turbo",        messages: [{ role: "user", content: prompt }],    });    res.json({        message: "Successful",        response: completion.data.choices[0].message.content,    });});

下面的代码片段从 React 应用程序承受 JSON 对象,应用 JSON 代码创立发问,并将其发送到 ChatGPT API。 蕴含与申请的 JSON 等效的 Typescript 的响应被发送回客户端。

因为咱们是从 Node.js 服务申请到响应,因而向应用程序增加 loading 状态用于在申请还没有返回时告诉用户正在申请中。

首先,创立一个 Loading.jsx 文件并将以下代码复制到该文件中

const Loading = () => {    return (        <div className='loading'>            <h2>Loading...</h2>        </div>    );};export default Loading;

App.jsx 文件中增加 loading 状态

const [loading, setLoading] = useState(false);

更新 handleSubmit 函数以在用户单击 “运行” 按钮或申请胜利时更新加载状态

const handleSubmit = () => {      //  关上 loading      setLoading(true);      fetch("http://localhost:4000/convert", {          method: "POST",          body: JSON.stringify({              value,          }),          headers: {              "Content-Type": "application/json",          },      })          .then((res) => res.json())          .then((data) => {              //  敞开 loading              setLoading(false);              setOutput(data.response);          })          .catch((err) => console.error(err));  };

有条件地渲染第二个代码编辑器,如下所示

return (        <main className='app'>           {/* -- 其余组件 --*/}            <div className='code__container'>              <div className='code'>                    <Editor                        height='90vh'                        className='editor'                        defaultLanguage='json'                        defaultValue='{ }'                        value={value}                        onChange={(value) => setValue(value)}                    />                </div>                <div className='output'>                  {loading ? (                      <Loading />                  ) : (                      <Editor                          height='90vh'                          className='editor'                          defaultLanguage='typescript'                          options={{                              domReadOnly: true,                              readOnly: true,                          }}                          defaultValue=''                          value={output}                          onChange={(value) => setOutput(value)}                      />                  )}                </div>            </div>        </main>    );

当用户提交一个 JSON 对象进行转换时,会立刻显示 Loading 组件,直到申请胜利,而后在代码编辑器上显示后果

祝贺! 利用就快要实现了。 接下来,让咱们增加一些额定的性能,例如通过单击按钮复制所有 Typescript 代码以及通过单击按钮革除输出编辑器的所有内容的能力。

复制 Typescript 代码

在这里,你将学习如何应用 React-copy-to-clipboard 库在单击按钮时复制和粘贴内容

咱们曾经在本教程结尾装置了该包。 接下来,将其导入 App.jsx 文件,如下所示。

import { CopyToClipboard } from "react-copy-to-clipboard";

在胜利复制内容后运行的 App.jsx 文件中的一个函数

const copyToClipBoard = () => alert(`已复制 ✅`);

编写 CopyToClipboard 组件,如下所示

<CopyToClipboard text={output} onCopy={copyToClipBoard}>    <span>        <Copy />    </span></CopyToClipboard>

CopyToClipboard 组件接管一个 text props(蕴含要复制的内容)和一个 onCopy 属性(一个在复制内容胜利后运行的函数)

删除用户输出

如果要删除所有用户的输出,须要将 value 作为 prop 传递到 <Delete/> 组件中

<Delete setValue={setValue} />

当用户单击删除图标时更新 value 状态

const Delete = ({ setValue }) => {    return (        <svg            xmlns='<http://www.w3.org/2000/svg>'            viewBox='0 0 24 24'            fill='currentColor'            className='w-6 h-6 deleteIcon'            onClick={() => setValue("{ }")}        >            <path                fillRule='evenodd'                d='M16.5 4.478v.227a48.816 48.816 0 013.878.512.75.75 0 11-.256 1.478l-.209-.035-1.005 13.07a3 3 0 01-2.991 2.77H8.084a3 3 0 01-2.991-2.77L4.087 6.66l-.209.035a.75.75 0 01-.256-1.478A48.567 48.567 0 017.5 4.705v-.227c0-1.564 1.213-2.9 2.816-2.951a52.662 52.662 0 013.369 0c1.603.051 2.815 1.387 2.815 2.951zm-6.136-1.452a51.196 51.196 0 013.273 0C14.39 3.05 15 3.684 15 4.478v.113a49.488 49.488 0 00-6 0v-.113c0-.794.609-1.428 1.364-1.452zm-.355 5.945a.75.75 0 10-1.5.058l.347 9a.75.75 0 101.499-.058l-.346-9zm5.48.058a.75.75 0 10-1.498-.058l-.347 9a.75.75 0 001.5.058l.345-9z'                clipRule='evenodd'            />        </svg>    );};export default Delete;

总结

到目前为止,咱们曾经学习了

  • ChatGPT 是什么
  • 如何在 React 应用程序中增加高效的代码编辑器
  • 如何在 Node.js 中与 ChatGPT 通信
  • 如何在 React 中单击按钮时复制与删除内容

本教程实现一个能够应用 ChatGPT API 构建的应用程序示例。 通过 API,你还能够创立功能强大的应用程序,在各个领域都有用,例如翻译、问答、代码解释或生成等。最初感激大家对本文的反对~欢送点赞珍藏,在评论区留下你的浅见

其余

  • 本教程的源代码可在此处取得:https://github.com/zidanDirk/json-to-typescript-chatgpt-cn
  • 本文为翻译文,原文地址