0

My directory goes like that

app/
  index.html
  script.js
  data.json

Sounds good? Now, I would like to choose a random object from my JSON data and present it to the user each time my document is loaded, good? Now I have a problem at that first part of it, getting the data from my data.json in the most optimal way possible. I can add an XMLHttpRequest() in my script.js to fetch the contents of my data.json or I would even use the fetch API, but I understand that these are made for "fetching" data across the web and are considered some sort of an overkill for such a simple task, I mean you don't need to send an HTTP request to link your CSS with your HTML, do you? So I figured out there must be a way to do that easily, one answer I found out there was to link your data as so <script id="data" src="./data.json" type="application/json"></script> and then you can document.getElementById("data") it, but that didn't work for me for some reason, one workaround that I came with was to change my data.json to data.js and just add a var data = prefix to my whole JSON data and then import that to my index.html and now I can access the variable data from my script, but I feel this is too hacky and isn't/shouldn't be the optimal to go around this. I think this scratches the topic of CORS/Same-origin which is a concept I have a feeble grasp on. A detailed explanation of what is going on in here would be greatly appreciated :)

EDIT: The answers provided speak solely of the fetch API, my issue is why is an HTTP request required to get access to a local file? why can't we link the JSON data through a link tag just like everything else e.g. our HTML, CSS, JS which are all linked using link/script tags.

aelmosalamy
  • 100
  • 9
  • Does this answer your question? [Relative paths with fetch in Javascript](https://stackoverflow.com/questions/36369082/relative-paths-with-fetch-in-javascript) – Shane Richards Apr 08 '20 at 19:30
  • This is actually interesting explanation in there. – aelmosalamy Apr 08 '20 at 20:00
  • But irrelevant to my question. – aelmosalamy Apr 09 '20 at 07:13
  • What's the type of you project? Is `app` a simple Apache folder that serves static data? Is this a Node.js project? JavaScript can't access on the local hard-disk by default. Node.js offers some addition APIs that [let you do this](https://stackoverflow.com/questions/10011011/using-node-js-how-do-i-read-a-json-file-into-server-memory). Depending on you type of project, there might be different solutions. – 3limin4t0r Apr 09 '20 at 10:09
  • It is just a basic static server, no Node.js involved, with `app/` being the root. – aelmosalamy Apr 09 '20 at 11:01

1 Answers1

1

I've come up with the three approaches below:

1) Fetch (or XHR) the .json file

I'd definitely regard using the Fetch API (or XHR) as the standard approach to enable a web document to retrieve a .json file from the server.

fetch('/app/data.json')
  .then(response => response.json())
  .then(json => console.log(json));

2) Reference a .js file instead of a .json file

ie. Use '/app/my-json-data.js' instead of '/app/data.json'

As you correctly point out in your question, you could upload a .js file to your server instead of a .json file, where, if your original JSON file '/app/data.json' looked like this:

{"Name" : "Data", "Section 1" : {"A" : "a", "B" : "b"}, "Section 2" : ["C", "D"]}

then your JS file '/app/my-json-data.js' would look like this, instead:

let myJSONData = '{"Name" : "Data", "Section 1" : {"A" : "a", "B" : "b"}, "Section 2" : ["C", "D"]}';

Then you could retrieve that JSON string into your document using:

<script src="/app/my-json-data.js"></script>

after which the string would exist in the document's javascript global scope as the variable myJSONData.

3) Embed the .json file in the document (via <object> or <iframe>)

When we were discussing earlier, I commented:

I guess because HTML lacks anything like <file type="application/json" src="/app/data.json" /> (analogous to <img src="/app/my-image.png" alt="My Image" />).

Then, I wondered if that was actually true. It turns out, it's not.

Here's a third way to retrieve the .json from the server:


Using HTML5 <embed>

<embed> appears to be locked and its contentDocument inaccessible. Not clear why.


Using HTML5 <object>

HTML:

<object data="/app/data.json" style="display: none"></object>

JS:

<script>
let myObject = document.getElementsByTagName('object')[0];

const getJSONFromObject = () => {
  console.log(myObject.contentDocument.body.textContent);
}

myObject.addEventListener('load', getJSONFromObject);
</script>

Using HTML5 <iframe>

HTML:

<iframe src="/app/data.json" style="display: none"></iframe>

JS:

<script>
let myIframe = document.getElementsByTagName('iframe')[0];

const getJSONFromIframe = () => {
  console.log(myIframe.contentDocument.body.textContent);
}

myIframe.addEventListener('load', getJSONFromIframe);
</script>

In order of personal preference, my favoured approaches would be:

  1. Fetch the .json file
  2. XHR the .json file
  3. Use a .js file instead of a .json file
  4. Embed the .json in the document via <object>
Rounin
  • 27,134
  • 9
  • 83
  • 108
  • But isn't the purpose of XHR/fetch is to get global files? In our scenario its local, why would I request my own server for a file? Isn't it like walking all the way to the post office to send a letter to your brother who is at the next room? – aelmosalamy Apr 08 '20 at 19:56
  • I guess because HTML lacks anything like `` (analogous to `My Image`). – Rounin Apr 09 '20 at 09:34
  • There is nothing such as ``; however, you can use a ` – aelmosalamy Apr 09 '20 at 10:47
  • Your answer is exactly that "hacky workaround" that I described in my question, which is sadly nothing new, I am asking for the CORRECT way to do it. – aelmosalamy Apr 09 '20 at 10:50
  • Can you explain why is fetch needed for a local file? – aelmosalamy Apr 09 '20 at 11:00
  • 1
    Sorry If I sounded "short-tempered" there, but I did actually mention that I added a variable assignment "prefix" before my JSON data, which is exactly what you mentioned. Thanks for the effort, I think I'll stick to fetch till I find a quenching answer. – aelmosalamy Apr 09 '20 at 11:06
  • @aelmosalamy - I've written up the third option above (after a lot of experimentation). I couldn't get `` to work, but I managed to import the `.json` into the document with both `` and ` – Rounin Apr 09 '20 at 15:29
  • 1
    Thank you, I tried iframe and it works like a breeze, but it's a bit in-intuitive, guess I will stick to XHR for now over fetch due to IE 9-11 compatibility. Thanks again mate! – aelmosalamy Apr 09 '20 at 15:46
  • You're most welcome. I added a final touch above for future visitors - the `` or ` – Rounin Apr 09 '20 at 15:53