0

I am taking a file input from a user and I want to check if the selected file is a JSON file. How can I do that?

<input type = "file" onChange = {checkJSON}/>

Also how do I retrieve data from the JSON file.

Shlok Sharma
  • 172
  • 1
  • 10
  • 2
    What server-side framework are you using? If you're asking about doing this client-side then the user hasn't actually "uploaded" anything. – Dai Jul 08 '22 at 10:02
  • I'm sorry I misused the work 'uploaded', basically when the user select a file using the input tag, I want to check if its a json file. – Shlok Sharma Jul 08 '22 at 10:07

2 Answers2

4

If JSON.parse throws an error, its most likely invalid, therefore you can check if its valid by getting the data into a string and then trying to parse it.

    try {  
      const json = JSON.parse(jsonStr);  
    } catch (e) {  
      console.log('invalid json');  
    }
CodingWolf
  • 106
  • 9
  • const checkJSON = (e) => { e.preventDefault(); try { const json = JSON.parse(e); } catch (e) { console.log('invalid json'); } } I'm still getting invalid json when i'm uploading a JSON file. – Shlok Sharma Jul 08 '22 at 10:12
  • @ShlokSharma **Use your debugger**. What is the exact actual error that is thrown? – Dai Jul 08 '22 at 11:36
  • @ShlokSharma The contents of the file are not in the value of the input element if the user just selected the file. It needs to be at least loaded into memory to work with it in JavaScript. You might want to take look here: https://developer.mozilla.org/en-US/docs/Web/API/File – Chris Jul 08 '22 at 15:14
-1

You can check if file extension is json and be sure that selected file is valid JSON in that way:

function Validate() {
  fileName = document.querySelector('#myfile').value;
  extension = fileName.split('.').pop();
  if (extension != "json")
  {
   alert("Sorry, " + fileName + " is invalid, allowed extension is json!");
   return false;
  }
  
  var file = document.getElementById('myfile').files[0];
  var reader = new FileReader();
  reader.readAsText(file, 'UTF-8');
  reader.onload = function(evt) {
    var jsondata = evt.target.result;
    try {  
      const json = JSON.parse(jsondata);  
      document.getElementById('jsondata').innerHTML = jsondata;
    } catch (e) {  
      alert("Sorry, " + fileName + " is not valid JSON file!");
      return false;  
    }
  }
  return true;
};

Html content:

<script src="script2.js"></script>
File: <input type="file" id="myfile" onchange="Validate()"/><br /><br />
<div id="jsondata"></div>

You can play with my little working live demo on ReplIt (both cases - onsubmit and onchange demos)

liketaurus
  • 152
  • 5
  • 1
    You should use `event.preventDefault()` instead of `return false;` in an event-listener. The `event` object is ambient in inline event-handler attributes. Like so: `
    ` and `function Validate(event, form) { if( is-invalid ) { event.preventDefault(); return; } }`
    – Dai Jul 08 '22 at 11:31
  • I downvoted this answer anyway because all this function does is check the file-extension: it doesn't actually verify the file contains valid JSON, and setting `innerHTML` to a non-sanitized user-supplied string is how you get XSS vulnerabilities: _don't do it_: use `.textContent` instead. – Dai Jul 08 '22 at 11:34
  • 1. original question has no words about contents of file or validity of JSON - question was how to check if the file is JSON file 2. you are right - textContent is better way, but in this case that's not a problem – liketaurus Jul 08 '22 at 15:05
  • The OP said " I want to check if the selected file is a JSON file" - which clearly means they want to see if the file actually is JSON - it is incredibly naïve to check only a file-extension., see here for example: https://stackoverflow.com/questions/64380151/why-would-i-not-want-to-trust-a-files-original-uploaded-file-extension – Dai Jul 08 '22 at 15:28
  • I`m not sure:) But I1ve updated my answer to check JSON validity – liketaurus Jul 08 '22 at 17:14
  • Your answer is still downvoted because _your code still doesn't work_: because `return true` inside the `onload` event-listener isn't going anywhere (event-handler return-values are ignored), and you've got a hard-coded `return true` at the bottom of `Validate()`. The `FileReader.readAsText` function is asynchronous, which means it simply cannot be used with the _synchronous_ `Validate()` function. – Dai Jul 11 '22 at 12:57
  • That's strange, because this code **works perfectly** - you can try it by yourself by following the [ReplIt](https://replit.com/@Babich/CheckFileExtension#index.html) link provided in the answer – liketaurus Jul 11 '22 at 13:18
  • It _doesn't_ "work perfectly" in the case where the `Validate()` function is called from an `submit` event-listener on the `
    ` element, for example.
    – Dai Jul 11 '22 at 13:25
  • Validate() is called exactly as shown in the answer (onchange for ). I provide a live demo on ReplIt that was tested with .txt file, with .json file that contains valid JSON, with .json file which is not JSON file actually. In all of these cases all works as expected. You can try it by yourself. – liketaurus Jul 11 '22 at 13:31
  • It's not about submit event, because author of question says " when the user select a file using the input tag, I want to check if its a json file" (see the second comment for question about misusing the word 'uploaded') – liketaurus Jul 11 '22 at 13:34
  • Even so, there's still a lot of room for improvement in your posted code: the superfluous `return true/false;` statements; it crashes if the user de-selects a file (as `files[0]` will be undefined); it only displays an `alert()` if a non-JSON file is selected but the _file will still be selected_ and it doesn't stop the user from submitting the `
    ` with it.; it uses a case-sensitive file-extension check; setting `innerHTML` instead of `textContent` will cause invalid HTML markup to be generated (and/or self-XSS) if the JSON contains angle-brackets. And it doesn't handle `multiple`. Etc.
    – Dai Jul 11 '22 at 13:41
  • Of course this code is not perfect - this is just a quick proof of concept how to check is file a JSON file, so it solves the problem. Improvements - is a next step. By the way, code not crashes when user deselect a file, and in this case we don't talk about submitting the form (actually we have no
    element at all). I used innerHTML only to demonstrate that contents of file was loaded (I'm sure that in final solution author will de-serialize a data and use it in other way). Other your comment are correct. But again this is the quick concept that solves exact this problem
    – liketaurus Jul 11 '22 at 13:46