arrow left
Back to Developer Education

    How To Format Form Data as JSON

    How To Format Form Data as JSON

    The browser Fetch API is used to make requests from a web page on the frontend to an API endpoint on the backend. <!--more--> On the other hand, the browser FormData API provides a precise way of accessing HTML form fields. These two native support browser APIs make it easy to send requests. Yet to send data as JSON to an API endpoint this requires extra work. In this tutorial, we will explore a step by step procedure on how to capture form field data, format them as JSON data and send it to an API endpoint.

    Table of contents

    Prerequisites

    To follow along with this tutorial a basic knowledge of the following is required:

    By the end of this tutorial, you should have a working HTML form that sends form data as JSON to an API endpoint. In the process, you will learn how to make use of the native browser Fetch and FormData APIs to achieve this goal. In the end, you will have a simple Express Node.js API which will listen for the request you send and send back the response.

    The HTML form template

    <form id="sample-form" method="post" action="http://localhost:5500/form">
      <h1>Sample Form</h1>
      <section>
        <fieldset>
          <h3>Gender</h3>
          <ul>
            <li>
              <label for="gender_1">
                <input type="radio" id="gender_1" name="gender" value="Male" />
                Male
              </label>
            </li>
            <li>
              <label for="gender_2">
                <input type="radio" id="gender_2" name="gender" value="Female" />
                Female
              </label>
            </li>
          </ul>
        </fieldset>
        <p>
          <label for="user-fullname">
            <span>Full Name: </span>
            <strong><abbr title="required">*</abbr></strong>
          </label>
          <input type="text" id="user-fullname" name="username" />
        </p>
        <p>
          <label for="user-mail">
            <span>E-mail: </span>
            <strong><abbr title="required">*</abbr></strong>
          </label>
          <input type="email" id="user-mail" name="usermail" />
        </p>
        <p><button type="submit">Submit Form</button></p>
      </section>
    </form>
    

    The HTML form

    Here we have a form with 2 radio buttons for selecting male or female gender and 2 input fields, for the full name and email address and a button to submit the form.

    Listening for the form submission

    Getting the form by ID.

    //Get the form element by id
    let sampleForm = document.getElementById("sample-form");
    

    When the form’s submit button is clicked the browser dispatches an event, which is captured by the form’s submit event listener. Define the event handler for the form when it's submitted and prevent the default browser behaviour so that you can handle it instead.

    //Define the event handler for the form when it's submitted
    sampleForm.addEventListener("submit", async (e) => {
      //Prevent browser default behavior
      e.preventDefault();
    
      // More code here in the next step
    }
    

    Reading the form field values with the FormData API

    The FormData API provides a precise way of accessing the HTML form field values by passing it a reference to the form element by getting the element attached to the event handler. Then get the URL from the form's action attribute.

    This obtains all the form fields and makes the form field values available as key-value pairs through a FormData instance. Then call the postFormFieldsAsJson() function (define it in the next step) and pass the url and the formData instance as arguments.

    //Define the event handler for the form when it's submitted
    sampleForm.addEventListener("submit", async (e) => {
      //Prevent browser default behavior
      e.preventDefault();
    
      //Get the entire form fields
      let form = e.currentTarget;
    
      //Get URL for api endpoint
      let url = form.action;
    
      try {
        //Form field instance
        let formFields = new FormData(form);
    
        //Call the `postFormFieldsJson()` function
        let responseData = await postFormFieldsAsJson({ url, formFields });
      } catch (error) {
        // Handle the error here.
        console.error(`An has occured ${error}`);
      }
    }
    

    Formating data to JSON and making a POST request

    Passing the FormData instance directly to fetch by default, the request body is formatted as "multipart" and the Content-Type on the request header is set to multipart/form-data. Convert the FormData instance to a plain object and then into a JSON string.

    Create an object from the formData instance using the Object.fromEntries() method.

    Using the JSON.stringify() method then format the plain form data as JSON.

    Specify the HTTP request method as POST and using the header field of the Fetch API specify that you are sending a JSON body request and accepting JSON responses back.

    Then set the request body as JSON created from the form fields. Now send the request and listen for the response. If the response is OK return the response body, otherwise throw an error.

    /**
     * Helper function to POST data as JSON with Fetch.
     */
    async function postFormFieldsAsJson({ url, formData }) {
      //Create an object from the form data entries
      let formDataObject = Object.fromEntries(formData.entries());
      // Format the plain form data as JSON
      let formDataJsonString = JSON.stringify(formDataObject);
    
      //Set the fetch options (headers, body)
      let fetchOptions = {
        //HTTP method set to POST.
        method: "POST",
        //Set the headers that specify you're sending a JSON body request and accepting JSON response
        headers: {
          "Content-Type": "application/json",
          Accept: "application/json",
        },
        // POST request body as JSON string.
        body: formDataJsonString,
      };
    
      //Get the response body as JSON.
      //If the response was not OK, throw an error.
      let res = await fetch(url, fetchOptions);
    
      //If the response is not ok throw an error (for debugging)
      if (!res.ok) {
        let error = await res.text();
        throw new Error(error);
      }
      //If the response was OK, return the response body.
      return res.json();
    }
    

    The complete code

    This is the full JavaScript code with inline comments from the steps above that: Captures the form fields using the browser FormData API, converts them to JSON and finally send them to an API endpoint using the browser Fetch API.

    //Get the form element by id
    const sampleForm = document.getElementById("sample-form");
    
    //Add an event listener to the form element and handler for the submit an event.
    sampleForm.addEventListener("submit", async (e) => {
      /**
       * Prevent the default browser behaviour of submitting
       * the form so that you can handle this instead.
       */
      e.preventDefault();
    
      /**
       * Get the element attached to the event handler.
       */
      let form = e.currentTarget;
    
      /**
       * Take the URL from the form's `action` attribute.
       */
      let url = form.action;
    
      try {
        /**
         * Takes all the form fields and make the field values
         * available through a `FormData` instance.
         */
        let formData = new FormData(form);
    
        /**
         * The `postFormFieldsAsJson()` function in the next step.
         */
        let responseData = await postFormFieldsAsJson({ url, formData });
    
        //Destructure the response data
        let { serverDataResponse } = responseData;
    
        //Display the response data in the console (for debugging)
        console.log(serverDataResponse);
      } catch (error) {
        //If an error occurs display it in the console (for debugging)
        console.error(error);
      }
    });
    
    /**
     * Helper function to POST data as JSON with Fetch.
     */
    async function postFormFieldsAsJson({ url, formData }) {
      //Create an object from the form data entries
      let formDataObject = Object.fromEntries(formData.entries());
      // Format the plain form data as JSON
      let formDataJsonString = JSON.stringify(formDataObject);
    
      //Set the fetch options (headers, body)
      let fetchOptions = {
        //HTTP method set to POST.
        method: "POST",
        //Set the headers that specify you're sending a JSON body request and accepting JSON response
        headers: {
          "Content-Type": "application/json",
          Accept: "application/json",
        },
        // POST request body as JSON string.
        body: formDataJsonString,
      };
    
      //Get the response body as JSON.
      //If the response was not OK, throw an error.
      let res = await fetch(url, fetchOptions);
    
      //If the response is not ok throw an error (for debugging)
      if (!res.ok) {
        let error = await res.text();
        throw new Error(error);
      }
      //If the response was OK, return the response body.
      return res.json();
    }
    

    The sample form data (formDataToJsonString) object sent as JSON;

    {
      "title": "Male",
      "username": "gisioraelvis",
      "usermail": "gisioraelvis@gmail.com"
    }
    

    Handling JSON request body in a Node.js and Express.js API

    Implementing a simple API using Node.js and Express.js, will expose an endpoint where you will be sending the request containing the form data as JSON.

    Setting up the API

    Node.js should be installed on your computer. To check if it is installed, run the following command:

    node -v
    

    Otherwise, install it using the following instructions.

    While within the project root folder, run the following npm command to initialize the Node.js project.

    npm init
    

    Fill in the relevant fields, and then proceed to the next steps.

    Alternatively, you can opt to auto initialize the project with NPM default values, in that case, run npm init -y. Check this in-depth npm guide to understand how to use NPM.

    npm packages used:

    • Express - To run the server and expose an endpoint that you will POST our request to. Here is a link to learn more about express.js.

    • Nodemon - This dev package ensures the server hot reloads as you make changes, so you don’t have to restart the server each time changes are made.

    • CORS or Cross-Origin Resource Sharing, allows you to send and accept requests from a different origin, bypassing the default securities applied to RESTful APIs. An awesome article on using cors in express.js.

    Installing the necessary dependencies

    This is all the steps to install the listed Node.js Packages:

    npm install cors express
    

    and

    npm install --save-dev nodemon
    

    The Express API/Server code.

    let express = require("express");
    let app = express();
    var cors = require("cors");
    //cors to allow cross origin resource sharing
    app.use(cors());
    //Middleware to parse the body of the request as JSON
    app.use(express.json());
    
    //The API endpoint that the form will POST to
    app.post("/formdata-as-json", (request, response) => {
      //Destructure the request body
      let resData = {
        serverData: request.body,
      };
    
      //Console log the response data (for debugging)
      console.log(resData);
      //Send the response as JSON with status code 200 (success)
      response.status(200).json(resData);
    });
    
    //Start the server on port 5500
    app.listen(5500, () => console.log(`we're live 🎉`));
    

    Configure the following start scripts in the package.json file.

    "dev": "nodemon api"
    

    To start the server run

    npm run dev
    

    The console response on the terminal from the API:

    The console response on the terminal from the API

    The console response on the browser:

    The console response on browser

    Here is the link to the full project on GitHub.

    Conclusion

    There you have it! A step by step process on how to format form data as JSON using the browser FormData API and POST it using the browser Fetch API to an API endpoint. You can utilize this newly gained knowledge and skills to develop other applications that make use of these powerful native browser APIs.

    Happy coding!


    Peer Review Contributions by: Jethro Magaji

    Published on: Feb 17, 2022
    Updated on: Jul 1, 2024
    CTA

    Cloudzilla is FREE for React and Node.js projects

    Deploy GitHub projects across every major cloud in under 3 minutes. No credit card required.
    Get Started for Free