Skip to content

M05 - Load and parse JSON

Introduction

Many dynamic application loads data from the internet. There are two major methods for retrieving data from most web services: XML or JSON. Nowadays web are heavily using JSON to store and transfer data between apps and server side.

JSON - JavaScript Object Notation

JSON is a dataformat which are heavily used to transfer data between client and server side. JSON files are lightweight, text-based, human-readable, and can be edited with a text editor. JSON a very popular format to create a different APIs. JSON data can be used with many different programming languages, not only with JavaScript.

In below example has friends key which points to an array of friends. Each friend object has a firstname, lastname and email keys with different values.

1
2
3
4
5
6
7
8
{
"friends":
 [
  {"firstname":"Mari", "lastname":"Ranta", "email":"mari@email.com"},
  {"firstname":"Kari", "lastname":"Ranta", "email":"kari@email.com"},
  {"firstname":"Sari", "lastname":"Ranta", "email":"sari@email.com"}
 ]
}

Developer need to use HTTP protocol to load/send JSON data. We will use fetchAPI in this course.

Fetch API

You can find more information from here:

Lets play first a little with JSON and create a few nodes to DOM.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<script>
let JSONFriendsObject = {"friends":[
  {"firstname":"Mari", "lastname":"Ranta", "email":"mari@email.com"},
  {"firstname":"Kari", "lastname":"Ranta", "email":"kari@email.com"},
  {"firstname":"Sari", "lastname":"Ranta", "email":"sari@email.com"}
]}

function init() {
  let element = document.getElementById("mylist");
  for(i=0; i< JSONFriendsObject.friends.length;i++) {
    let li = document.createElement("li");
    let text = document.createTextNode(
      JSONFriendsObject.friends[i].firstname+ " " +
      JSONFriendsObject.friends[i].lastname+ " " +
      JSONFriendsObject.friends[i].email);
    li.appendChild(text);
    element.appendChild(li);
  }
}

</script>

<body onload="init();">
   <ul id="mylist">
   </ul>
</body>

Will display:

1
2
3
* Mari Ranta mari@email.com
* Kari Ranta kari@email.com
* Sari Ranta sari@email.com

JSON conversion

Sometimes developer need to convert JSON string to object or JSON object to string. Developer can then use following methods:

  • JSON.parse convert JSON text string to JSON object
  • JSON.stringify convert JSON object to string

Example with JSON parse. Use case - JSON has been loaded from server side as a string.

1
2
3
let obj = JSON.parse('{"firstName":"John", "lastName":"Doe"}');
console.log(obj.firstName); // John
console.log(obj.lastName);  // Doe

Example with JSON stringify. Use case - JSON object need to be send to server side as a string.

1
2
3
4
var obj = { "name":"John", "age":30, "city":"New York"};
var myJSON = JSON.stringify(obj);
document.getElementById("demo").innerHTML = myJSON; 
// "{"name":"John","age":30,"city":"New York"}"

Asynchronous Programming

Synchronous vs Asynchronous**

  • Synchronous real-time operations, e.g. function code lines are executed from start to end without being able to do anything else at the same time
  • Asynchronous operations, e.g. function code lines, can be performed by starting several parallel sets of operations.

Example - Synchronously working restaurant waiter

  1. can take order #1 from table #1
  2. passes order #1 to the cook
  3. waiting for the cook to finish the dish
  4. serve order #1
  5. can take next order #2 from table #2

Example - Asynchronously working restaurant waiter

  1. can take order #1 from table #1
  2. passes order #1 to the cook
  3. can take order #2 from table #2
  4. passes order #2 to the cook
  5. after being informed of the completion of order #1 to serve it

Working with JavaScript you should not wait that you will get a answer from server side. You can let your application do something else at the same time. Come back when data is loaded and parse/show it to your UI.

Promise Object

The Promise object represents the eventual completion (or failure) of an asynchronous operation and its resulting value. It will give a promise that after execution data is or not loaded successfully.

Promise has one of the following states:

  • pending: initial state, neither fulfilled nor rejected (result: undefined)
  • fulfilled: meaning that the operation was completed successfully (result: value)
  • rejected: meaning that the operation failed (result: error)

Promise object syntax:

1
2
3
let promise = new Promise(function(resolve, reject) {
  // code lines here
});
  • resolve function will be called if operation was completed successfully
  • reject function will be called if operation was not completed successfully

Small example:

1
2
3
4
5
6
7
8
let honest = true;
const promise = new Promise((resolve, reject) => {
  if (honest) {
    setTimeout(() => resolve("I kept my promise, the decision took a second"), 1000);
  } else {
    reject("I couldn't keep my promise")
  }
})

Above promise can be tested with own made checkPromise function.

  • then method will be called if resolve function is called inside promise object (ok).
  • catch method will be called if reject function is called inside promise object (error).
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const checkPromise = () => {
  promise
    .then(ok => {
      console.log(ok)
    })
    .catch(err => {
      console.error(err)
    })
}

checkPromise();

Test

Remember test above code with honest variable true and false situations.

  • honest is true it should display in console: "I kept my promise, the decision took a second"
  • honest is false it should display "I couldn't keep my promise"

Fetch API

The Fetch API provides an interface which can be used with JavaScript to send HTTP requests to server side and handle HTTP responses from the server side. It will seem familiar to anyone who has used XMLHttpRequest, but the new API provides a more powerful and flexible feature set.

A following JSON data will be used in a below examples. You can save it as a highscores.json file to your local computer.

1
2
3
4
5
[
    { "name":"Guru Ken","score":9000 },
    { "name":"Saurus Tino", "score":7000 },
    { "name":"Linko Lumi", "score":5000 }
]

Fetch is making a HTTP request to highscores.json file using a fetch() function and it will return a promise object and developer can use then and catch to detect if data is loaded successfully or not.

1
2
3
4
fetch('highscores.json')
    .then(response => response.json())  // change data to JSON object
    .then(data => console.log(data))    // show data in web browsers console
    .catch(err => console.log('Request Failed', err)); // handle error

Create a sample HTML file and load highscore data.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
  <head>
    <title>Fetch API Example</title>
    <meta charset="utf-8">
  </head>
  <body>
    <h1>Fetch API Example</h1>
    <script>
      fetch('highscores.json')
        .then(response => response.json())  
        .then(data => console.log(data))   
        .catch(err => console.log('Request Failed', err));
    </script>      
  </body>
</html>

You need to run your code in some server side. Use JAMK/IT student or just install Live Server to your Visual Studio Code.

You should see your JSON data array in your web browsers console.

Image 01

Fetch and file:/// protocol

You can't load JSON data from file:/// protocol. You need to use real http(s):/// connection.

There’s a special syntax to work with promises in a more comfortable fashion, called async and await. It’s surprisingly easy to understand and use.

1
2
3
4
5
6
7
8
9
async function fetchHighscores() {
  try {
    let response = await fetch('highscores.json');
    let data = await response.json();
    console.log(data);
   } catch (error) {
    console.log(error);
   }
}
  • async keyword is used with function
  • await keyword is working only inside async functions
  • Promises that uses a await keyword are executed asyncronously / non-blocking
  • Execution continues below await line, if promise got fulfilled status
  • Use try-catch to handle error

Complete example - Load JSON data and create li elements to ul list.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
<html>
<head>
  <title>Fetch API Example</title>
  <meta charset="utf-8">
</head>
<body>
  <h1>Fetch API Example</h1>
  <ul id="result"></ul>
  <script>
    async function fetchHighscores() {
      try {
        let response = await fetch('highscores.json');
        return await response.json();
      } catch (error) {
        console.log(error);
      }
    }
    async function renderHighscrores() {
      let highscores = await fetchHighscores();
      let ul = document.getElementById("result");
      highscores.forEach(highscore => {
        let li = document.createElement("li");
        let text = document.createTextNode(`${highscore.name} :  ${highscore.score}`);
        li.appendChild(text);
        ul.appendChild(li);
      });
    }
    renderHighscrores();
  </script>      
</body>
</html>
  • renderHighscrores() function will be used to start fetching highscores
  • fetchHighscores will use JavaScript's fetch function to get JSON data
  • forEach fill loop all highscore objects and a new li element will be added to the list

CORS

Usually developer need to fetch data from different server than where HTML/JavaScript file is. Then developer will need to get familiar with a CORS.