DEV Community

Cover image for Make JSON file validator in just 5 lines ๐Ÿ‘€
Tim
Tim

Posted on • Edited on

Make JSON file validator in just 5 lines ๐Ÿ‘€

In my previous post, I reviewed the different web APIs for working with files. In this post, we will put that knowledge to use and make a simple JSON file validator web app.

A user can go to our app, upload their JSON file, and it will tell them if it is valid or not, all from the browser. No dependencies, no call to external APIs. Just pure JavaScript and HTML.

First the boilerplate HTML, CSS, and element selectors.

<div class="container">
  <h1><code>JSON</code> validator</h1>
  <input name="file" accept=".json" type="file" id="file-input" />
  <div id="message" />
</div>
Enter fullscreen mode Exit fullscreen mode

The attribute type="file" tells the browser to render a file selector instead of a normal text input. accept=".json" tells the browser to only allow the user to select JSON files.

<style>
  .container {
    padding-top: 10px;
    max-width: 500px;
    margin: auto;
    display: flex;
    flex-direction: column;
  }
  h1 {
    font-size: 30px;
  }
  code {
    border-radius: 3px;
    background-color: gainsboro;
    padding: 4px;
    font-size: 0.9em;
  }
  #message {
    padding-top: 20px;
    font-size: 20px;
  }
</style>
Enter fullscreen mode Exit fullscreen mode
<script type="module">
  const input = document.getElementById("file-input");
  const message = document.getElementById("message");
</script>
Enter fullscreen mode Exit fullscreen mode

To start, add an event listener to the input's change event. The callback will receive an event with the <input> as its target. The input the user selects is accessible via the files attribute, which is a list of Files. Since our input only takes one file, we will take the file at index 0 of the list.

addEventListener("change", (e) => {
  const file = e.target.files[0];
});
Enter fullscreen mode Exit fullscreen mode

Next, we need to get the text in the file. This is where the magic of web APIs comes in. A File is a wrapper around another web API, Blob (funny name, I know. It actually is shorthand for binary large object). So anything a Blob can do, a File can do, which is handy because Blob has a method, .text(), which returns the file content as text. Perfect.

.text() returns a promise, so we will make our function async and await the result.

addEventListener("change", async (e) => {
  const file = e.target.files[0];
  const text = await file.text();
});
Enter fullscreen mode Exit fullscreen mode

With the text of the file in hand, we can do our JSON validation with yet another web API available in all browsers, JSON.parse(). This method takes a string as its argument and converts it to a JavaScript object if it is valid JSON or it will throw an error if it's not valid JSON. So all the hard work of parsing and checking the string is done for us by the browser!

Since there is the potential of an error being thrown, we need to wrap the function call in a try...catch block.

input.addEventListener("change", async (e) => {
  const file = e.target.files[0];
  const text = await file.text();
  try {
    JSON.parse(text);
    // Do something if it works
  } catch (e) {
      // Do something if it fails
  }
});
Enter fullscreen mode Exit fullscreen mode

If the JSON file is invalid, no code below JSON.parse(text) and above catch will run. Instead, it will jump directly to the code inside the catch block.

This means we can put the code to handle valid JSON under JSON.parse(text) and the code to handle invalid JSON under catch.

To alert the user if their JSON file is valid, we will append HTML inside of the <div id="message" />.

The error thrown by .parse() should look something like JSON.parse: (some generic error message) at line 2 column 3 of the JSON data. By splitting the error message string on the word at we can get the location of the error in the JSON file to display to the user.

input.addEventListener("change", async (e) => {
  const file = e.target.files[0];
  const text = await file.text();
  try {
    JSON.parse(text);
    message.innerHTML = `<div>Valid <code>JSON</code> โœ…<div/>`;
  } catch (e) {
     message.innerHTML = `<div>Invalid <code>JSON</code> โŒ at ${e.message.split(" at ")[1]}<div/>`;
  }
});
Enter fullscreen mode Exit fullscreen mode

And there you have it. A fully functional JSON validator. Here is the full HTML file you can copy and play around with and a live demo to prove that it works!

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JSON Validator</title>
    <script type="module">
      const input = document.getElementById("file-input");
      const message = document.getElementById("message");

      input.addEventListener("change", async (e) => {
        const file = e.target.files[0];
        const text = await file.text();
        try {
          JSON.parse(text);
          message.innerHTML = `<div>Valid <code>JSON</code> โœ…<div/>`;
        } catch (e) {
          message.innerHTML = `<div>Invalid <code>JSON</code> โŒ at ${e.message.split(" at ")[1]}<div/>`;
        }
      });
    </script>
    <style>
      body {
        font-size: 16px;
      }
      .container {
        padding-top: 10px;
        max-width: 500px;
        margin: auto;
        display: flex;
        flex-direction: column;
      }
      h1 {
        font-size: 30px;
      }
      code {
        border-radius: 3px;
        background-color: gainsboro;
        padding: 4px;
        font-size: 0.9em;
      }
      #message {
        padding-top: 20px;
        font-size: 20px;
        font-weight: 500;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h1><code>JSON</code> validator</h1>
      <input name="file" accept=".json" type="file" id="file-input" />
      <div id="message" class="message" />
    </div>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Top comments (3)

Collapse
 
fyodorio profile image
Fyodor

Now show me the pointer to where exactly my JSON is wrong ๐Ÿ˜๐Ÿ˜‰

Collapse
 
tmrc profile image
Tim • Edited

Good idea! I updated the code example and demo site to show a way that could be done using the error message returned by .parse(), which will contain the location of the error in the JSON.

Collapse
 
fyodorio profile image
Fyodor