TL;DR
In this article, you'll learn how to build a web application that converts JSON objects to Typescript interfaces using the ChatGPT API.
Why do you need it?
Many websites offer API for different stuff.
The main problem usually is when writing code, your code needs to be made aware of the response, and as a result, you don't get completion.
The solution is to send one request, get the result, and map it into interfaces.
Another option is to look for the result over the website documentation (if they have one) and map it into interfaces.
But a much simpler solution is sending JSON and returning the interface in Typescript. Easy.
You can do it with JSON-to-typescript libraries, but I am going to show you this with ChatGPT because, you know, I like magic 🪄⭐️
HELP ME OUT
I have created the repo with the full code to turn JSON to Typescript feel free to clone, use it, and give me a star ⭐️ 🥰
https://github.com/novuhq/json-to-typescript-chatgpt
What is ChatGPT?
ChatGPT is an AI language model trained by OpenAI to generate text and interact with users in a human-like conversational manner. Users can submit requests and get information or answers to questions from a wide range of topics in just a few seconds.
ChatGPT also helps with writing, debugging, and explaining code snippets. It is worth mentioning that ChatGPT and its API are currently free and open to public use.
Therefore, in this article, we'll use its API to build a JSON to Typescript converter.
Project Setup
Here, I'll guide you through creating the project environment for the web application. We'll use React.js for the front end and Node.js for the backend server.
Create the project folder for the web application by running the code below:
mkdir json-to-typescript
cd json-to-typescript
mkdir client server
Setting up the Node.js server
Navigate into the server folder and create a package.json
file.
cd server & npm init -y
Install Express, Nodemon, and the CORS library.
npm install express cors nodemon
ExpressJS is a fast, minimalist framework that provides several features for building web applications in Node.js; CORS is a Node.js package that allows communication between different domains, and Nodemon is a Node.js tool that automatically restarts the server after detecting file changes.
Create an index.js
file - the entry point to the web server.
touch index.js
Set up a Node.js server using Express.js. The code snippet below returns a JSON object when you visit the http://localhost:4000/api
in your browser.
//👇🏻index.js
const 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(`Server listening on ${PORT}`);
});
Configure Nodemon by adding the start command to the list of scripts in the package.json
file. The code snippet below starts the server using Nodemon.
//In server/package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon index.js"
},
Congratulations! You can now start the server by using the command below.
npm start
Setting up the React application
Navigate into the client folder via your terminal and create a new React.js project.
cd client
npx create-react-app ./
Install the Monaco Editor for React and the React Copy to Clipboard libraries.
npm install @monaco-editor/react react-copy-to-clipboard
Monaco Editor for React is a simple package for adding code editors to React apps, and the React Copy to Clipboard package allows us to copy and paste contents via a button click.
Delete the redundant files, such as the logo and the test files from the React app, and update the App.js
file to display "Hello World" as below.
function App() {
return (
<div>
<p>Hello World!</p>
</div>
);
}
export default App;
Navigate into the src/index.css
file and copy the code below. It contains all the CSS required for styling this project.
@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;
}
Building the application user interface
Here, we'll create the user interface for the JSON to Typescript converter to enable users to add JSON objects on the left-hand side of the screen and view the results in Typescript on the right-hand side of the screen.
To begin with, create an icons
folder within the client/src
folder. The icons
folder will contain the delete and copy icon from the image above.
cd client/src
mkdir icons
cd icons
touch Copy.js Delete.js
Update the Copy.js
file to contain the SVG icon from Heroicons.
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;
Copy the code below into the Delete.js
file. It renders an SVG icon for the delete button.
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;
Update the App.js
file to render the header elements as done below.
import React from "react";
import Delete from "./icons/Delete";
import Copy from "./icons/Copy";
const App = () => {
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 className='header'>
<h3>Typescript</h3>
<Copy />
</div>
</header>
<div className='code__container'></div>
</main>
);
};
export default App;
The code snippet above displays the header components of the web application. In the upcoming section, I'll guide you on how to add the Monaco code editor to the React application.
Add the Monaco code editor to React
The Monaco Editor is a well-known web technology-based code editor that powers VS Code, and it just requires a one-line integration to support multiple programming languages.
We've installed the library in the previous section. Next, import it into the App.js
file as done below.
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;
- From the code snippet above,
- I imported the
Editor
component from the Monaco Editor package. - The first editor component accepts props such as - height, value, language, and the
onChange
event prop. - The second editor component accepts the same props as the first but with an additional prop called
options
that prevents users from editing its values since it's read-only.
- I imported the
How to communicate with ChatGPT in Node.js
In this section, you'll learn how to communicate with the ChatGPT via its API in a Node.js server. We'll send the JSON code provided by the user to the API to convert the code to its Typescript equivalent. To accomplish this:
Install the OpenAI API Node.js library by running the code below.
npm install openai
Log in or create an OpenAI account here
Click Personal
on the navigation bar and select View API
keys from the menu bar to create a new secret key.
Copy the API Key somewhere safe on your computer; we'll use it shortly.
Configure the API by copying the code below into the index.js
file. Replace the value of the apiKey
with your API Key.
const { Configuration, OpenAIApi } = require("openai");
const configuration = new Configuration({
apiKey: "<YOUR_API_KEY>",
});
const openai = new OpenAIApi(configuration);
Create a POST route on the server that will accept the JSON code from the front end and generate its Typescript equivalent.
app.post("/convert", (req, res) => {
console.log(req.body);
});
Update the handleSubmit
function within the App.js
file to send the JSON object provided by the user to the /convert
endpoint on the server.
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));
};
Update the /convert
endpoint as done below.
app.post("/convert", async (req, res) => {
//👇🏻 Destructure the JSON object
let { value } = req.body;
//👇🏻 the ChatGPT prompt
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,
});
});
The code snippet above accepts the JSON object from the React app, creates a prompt with the JSON code, and sends it to the ChatGPT API. The response containing the Typescript equivalent of the code is sent back to the client.
Since we've retrieved the response from the Node.js server, add a loading state to the application to notify the users when the request is pending.
To begin with, create a Loading.js
file and copy the code below into the file.
import React from "react";
const Loading = () => {
return (
<div className='loading'>
<h2>Loading...</h2>
</div>
);
};
export default Loading;
Add a loading state within the App.js
file.
const [loading, setLoading] = useState(false);
Update the handleSubmit
function to update the loading state when a user clicks the Run button or when the request is successful.
const handleSubmit = () => {
//👇🏻 sets to true
setLoading(true);
fetch("http://localhost:4000/convert", {
method: "POST",
body: JSON.stringify({
value,
}),
headers: {
"Content-Type": "application/json",
},
})
.then((res) => res.json())
.then((data) => {
//👇🏻 sets to false
setLoading(false);
setOutput(data.response);
})
.catch((err) => console.error(err));
};
Conditionally render the second code editor containing the output as done below.
return (
<main className='app'>
{/* -- other UI components --*/}
<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>
);
When a user submits a JSON object for conversion, the Loading component is displayed immediately until the request is successful, then the result is displayed on the code editor.
Congratulations!🎊 The application is almost complete. Next, let's add some extra features, such as the ability to copy all the Typescript code via a button click and clear all the content of the input editor via a button click.
How to copy the Typescript code via a button click
Here, you'll learn how to copy and paste content on a button click using the React-copy-to-clipboard library.
You've already installed the package at the beginning of this tutorial. Next, import it into the App.js
file as done below.
import { CopyToClipboard } from "react-copy-to-clipboard";
Create a function within the App.js
file that runs after the content has been successfully copied.
const copyToClipBoard = () => alert(`Copied ✅`);
Wrap the CopyToClipboard
component from the package around the SVG icon as done below.
<CopyToClipboard text={output} onCopy={copyToClipBoard}>
<span>
<Copy />
</span>
</CopyToClipboard>
The CopyToClipboard
component accepts a text prop - containing the content to be copied and an onCopy
prop - a function that runs when the content is copied.
Deleting all the user’s input via a button click
To delete all the user's input, pass the value
state as a prop into the <Delete/>
component.
<Delete setValue={setValue} />
Update the value
state when a user clicks the delete icon.
import React from "react";
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;
Conclusion
So far, you've learnt,
- what ChatGPT is,
- how to add an efficient code editor in a React app,
- how to communicate with ChatGPT in Node.js, and
- how to copy contents on button click in React.
This tutorial walks you through an example of an application you can build using the ChatGPT API. With the API, you can create powerful applications useful in various fields, such as translators, Q&A, code explanation or generation, etc.
The source code for this tutorial is available here:
https://github.com/novuhq/json-to-typescript
Thank you for reading!
HELP ME OUT
I have created the repo with the full code to turn JSON to Typescript feel free to clone, use it, and give me a star ⭐️ 🥰
Top comments (13)
Awesome article! Learning how to use the ChatGPT API to convert JSON to Typescript interfaces is super helpful. This will save a ton of time for devs who work with APIs a lot. The step-by-step instructions are easy to follow, even for beginners. And the integration with the web app is seamless. Overall, this article is an excellent resource for anyone who wants to speed up their dev process. Thanks for sharing!
Thank you so much Emil! 🚀
Overall this comment seems to be written by chatgpt
Hi @cwtuan, I found another good online tool to convert JSON to typescript. Which also provides some extra features like repairing broken JSON (Only for minor issues in JSON), formatting JSON, and converting JSON files to typescript, etc.
This is really great write up 👌🏻, thanks for sharing it.
Thank you Sachin!
const prompt =
Convert the JSON object into Typescript interfaces \n ${value} Please, I need the only the code, I don't need any explanations.
;I guess it will work, even through in your prompt you said 'I need the only the code'
Nice and simple approach.
Couldn't you also validate the output of chatgpt by checking that the object conforms to the type using typescript? You could even feed the type error into chatgpt to see if it can fix it with a second attempt
Thank you for writing my comment for me!
You can do the same without any AI and it will be more reliable and cheaper
Perfect use of ChatGPT. Great job..
Cool idea and well explained.
One small suggestion: you should also clear the loading flag in the error handler, not just when it succeeds. And you might need an error state and component as well.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.