Building a JSON to Typescript converter with React, NodeJS and ChatGPT 🚀
Tags: webdev, javascript, programming, tutorial
Published: 2023-03-13 13:03:06

# 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](https://www.npmjs.com/package/json-to-ts) libraries, but I am going to show you this with ChatGPT because, you know, I like magic 🪄⭐️

![meme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cv4tbavjp0q85yu0qlex.jpeg)


## 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


![Help](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/go9s8h1g313nit4k6bc4.gif)

## What is ChatGPT?

ChatGPT is an AI language model trained by [OpenAI](https://openai.com/) 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](https://openai.com/blog/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:

```bash
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.

```bash
cd server & npm init -y
```

Install Express, Nodemon, and the CORS library.

```bash
npm install express cors nodemon
```

[ExpressJS](https://expressjs.com/) is a fast, minimalist framework that provides several features for building web applications in Node.js; [CORS](https://www.npmjs.com/package/cors) is a Node.js package that allows communication between different domains, and [Nodemon](https://www.npmjs.com/package/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.

```bash
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.

```jsx
//👇🏻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.

```json
//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.

```bash
npm start
```

### Setting up the React application

Navigate into the client folder via your terminal and create a new React.js project.

```bash
cd client
npx create-react-app ./
```

Install the [Monaco Editor for React](https://github.com/suren-atoyan/monaco-react) and the [React Copy to Clipboard](https://www.npmjs.com/package/react-copy-to-clipboard) libraries.

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

[Monaco Editor for React](https://github.com/suren-atoyan/monaco-react) is a simple package for adding code editors to React apps, and the [React Copy to Clipboard](https://www.npmjs.com/package/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.

```jsx
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.

```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;
}
```

## 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.

![Begin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pgy5kec93zlm23sbl77p.png)

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.

```bash
cd client/src
mkdir icons
cd icons
touch Copy.js Delete.js
```

Update the `Copy.js` file to contain the SVG icon from [Heroicons](https://heroicons.com/).

```jsx
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.

```jsx
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.

```jsx
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.

```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;
```

- 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.


![Interface](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1eph3a53wh2v228tpa2g.png)


## 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.

```bash
npm install openai
```

Log in or create an OpenAI account [here](https://platform.openai.com/overview)

Click `Personal` on the navigation bar and select `View API` keys from the menu bar to create a new secret key.

![Personal](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ivqskomtlvknyp62e2dd.png)

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.

```jsx
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.

```jsx
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.

```jsx
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.

```jsx
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.

```jsx
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.

```jsx
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.

```jsx
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.

```jsx
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.

![Successful](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iec9awzh8424vmewtr3m.png)


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](https://www.npmjs.com/package/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.

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

Create a function within the `App.js` file that runs after the content has been successfully copied.

```jsx
const copyToClipBoard = () => alert(`Copied ✅`);
```

Wrap the `CopyToClipboard` component from the package around the SVG icon as done below.

```jsx
<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.

```jsx
<Delete setValue={setValue} />
```

Update the `value` state when a user clicks the delete icon.

```jsx
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](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 ⭐️ 🥰

https://github.com/novuhq/json-to-typescript-chatgpt