Get free points Front-end week
Get up to 40 % extra points for free! More info
Save up to 80 % on HTML & CSS + JavaScript e-learning! Only this week!

Lesson 6 - Objects, JSON, And Enhancing the JavaScript Diary

In the previous lesson, Creating an OOP Diary In JavaScript, we started to program our JavaScript diary. In today's object-oriented programming tutorial, we're going to continue with it. We'll look at the JSON format and local data storage.

JSON

JSON is an abbreviation of JavaScript Object Notation and, to put it simply, JSON is a JavaScript object written as a string. We can save objects converted to JSON to files or to other storages simply and then load them back from them. In addition to XML, it's also a popular data format for APIs, when our application asks a server for some data and the server sends it back as JSON objects.

Syntax example

Let's consider we have an instance, for example a specific user with a name and age. We'd create such an instance like this (assuming that the class has the appropriate constructor):

const simon = new User("Simon", 19);

If we converted this instance to JSON, the JSON would look like this:

{
    "name": "Simon",
    "age": 19
}

We declare JSON objects using braces. Then the names of its properties follow, with colons and their values.

We don't write a comma after the last value of the block. Some JS engines may have a problem with it otherwise.

The great advantage of JSON is that it's part of the JavaScript language. So we don't need any libraries and once we load JSON data, we have it as objects instantly. So, if we store the JSON above into a variable, there will be an object with the name and age properties:

const simon = {
    "name": "Simon",
    "age": 19
};
document.write(`${simon.name}, ${simon.age}`);

The script will really print the JSON data on the page:

Your page
localhost

This is, however, not a User instance, because JSON objects are anonymous objects. JSON format does not support object methods, and only supports the string, number, object, boolean, null, and array data types for properties. Therefore, JSONs are only data, not objects containing any logic.

In JavaScript, you can sometimes encounter similar anonymous objects, they are used in places where it wouldn't be worthwhile to declare a fully-featured class. We could even add methods to these objects in JavaScript code, but never in JSON files directly. We definitely should not use anonymous objects instead of standard instances.

Let's show one more JSON, this time a more complicated one with a nested object and an array:

{
    "name": "Simon",
    "age": 19,
    "skills": ["programming", "graphics", "swimming"],
    "car": {
        "license_plate": "13ABC",
        "abs": true
    },
    "wife": null
}

The JSON above defines, in addition to the user's name and age, his skills, car, and wife. It's still a data definition of one particular instance. Unlike objects, we declare arrays using brackets. Notice the nested object representing a car. So far Simon has no wife. Again, notice the missing commas after the last values of the blocks.

Parsing JSON

Of course, JSON often comes to us as a string rather than declared in a nice and neat JS file. We load such JSON using the JSON.parse() method. Let's show our JSON example with the user, this time declared as text:

const simon = JSON.parse(`{
    "name": "Simon",
    "age": 19
}`);
document.write(`${simon.name}, ${simon.age}`);

Again, the output is the same as in the previous example:

Your page
localhost

Converting objects to JSON

And how, on the other hand, will we convert some of our object to a JSON string? To do that, we use the JSON.stringify() method. Let's really create a User class to have a complete example:

class User {

    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    greet() {
        alert("Hello!");
    }

}

We added the greet() method to the above class to make sure it really won't work in JSON. Let's create a User class instance and convert it to a JSON string:

const simon = new User("Simon", 19);
const json = JSON.stringify(simon);

document.write(json);

Our object will be printed as JSON:

Your page
localhost

We can see that there's no information about which class the user was created from, and all the logic is missing. The code is all on one line because by default, JSON.stringify() saves space and doesn't add white characters to the resulting string.

LocalStorage

We'd be already able to save our diary entries to JSON. We'll use localStorage to save them. It's a storage in the user's web browser (hence local) where data can be stored as a string that can be accessed later. We have 10MB of space available for our application, which is really a lot of text :)

Using the storage will help us handle data persistence in our application. Of course, if we refresh the page now, our entries will be lost. That's why we'll convert our entry array to JSON and save it to localStorage. We'll then parse it from the storage back to the array when the page is loaded. So the data will remain in the application.

Working with localStorage

localStorage is very easy to use. We use the setItem() method to store a string under a string index. Similarly, to read a value under a key, we use getItem().

Let's store the string "data" under the "property" key:

localStorage.setItem("property", "data");

Now we'll print what's under the "property" key, which will result in getting the "data" value:

document.print(localStorage.getItem("property"));

The result:

Your page
localhost

Enhancing the Diary

Finally, we can proceed to the conclusion of today's lesson and modify the diary to save and load data from/to localStorage. We'll store our entries array in the Diary class simply under the entries key.

The Constructor

So instead of creating an empty entry array in the diary constructor, we'll load the entries from the local storage:

constructor(language = "en-US") {
    const storageEntries = localStorage.getItem("entries");
    this.entries = storageEntries ? JSON.parse(storageEntries) : [];
    this.language = language;

    this.nameInput = document.getElementById("name");
    this.dateInput = document.getElementById("date");
    this.confirmButton = document.getElementById("confirm");
    this.printElement = document.getElementById("task-list");

    this.setEvents();
}

We store our entries from localStorage to the storageEntries variable. Next, we need to check if any entries are stored at all. If not, the storageEntries variable will be null. That's why we used a ternary operator, thanks to which the entries property is set to either the parsed array from localStorage or to an empty array.

So we got loading the entries from localStorage, now we'll add saving them at the time a new entry has been added. We'll store the entries in both the entries array and the storage. Working with the storage only in the entire application would require constant conversion of object entries to strings and back. Therefore, we'll use the storage only for loading the entries at the start and to storage newly edded entries.

We'll add one line to the setEvents() method, saving a new entry to the storage as well:

setEvents() {
    this.confirmButton.onclick = () => {
        const entry = new Entry(this.nameInput.value, this.dateInput.value);
        this.entries.push(entry);
        localStorage.setItem("entries", JSON.stringify(this.entries)); // the line added
        this.printEntries();
    };
}

We can try to run the project, add tasks, and reload the page. The tasks now stay in the app and that means that you have your first real object-oriented application. Congratulations! That's all for today, we've solved our storage problem quite easily. In the next lesson, Improving the Object-Oriented Diary In JavaScript, we'll finish the diary :)


 

 

Activities (2)

 

 

Comments

To maintain the quality of discussion, we only allow registered members to comment. Sign in. If you're new, Sign up, it's free.

No one has commented yet - be the first!