Module 9 - JavaScript Object Notation (JSON)

Introducing JSON

What is JSON?

JSON (JavaScript Object Notation) is a lightweight format used to store and exchange data. It’s widely used in web development to transfer information between a server and a web client, such as when a web application needs to load or save data asynchronously without reloading the entire page. JSON is not only human-readable but also easy for computers to parse and generate, making it a universal data format.

What Does JSON Look Like?

JSON is structured in a way that resembles JavaScript objects, which is convenient for working with data in JavaScript. However, it has stricter syntax rules to ensure consistent formatting.

Basic Syntax Rules for JSON:

  • Data is presented in key-value pairs.
  • Keys must be strings enclosed in double quotes (""). Single quotes are not allowed for keys in JSON.
  • Values can be:
    • A string (enclosed in double quotes)
    • A number
    • An object (another set of key-value pairs, enclosed in curly braces {})
    • An array (a list of values, enclosed in square brackets [])
    • A boolean (true or false)
    • null (to represent an empty or non-existent value)
  • Data is separated by commas between key-value pairs.
  • Objects are enclosed in curly braces {}, and arrays are enclosed in square brackets [].

Comparison to JavaScript Objects

While JSON looks a lot like JavaScript objects, there are a few important differences:

  • Strings in JSON must use double quotes, whereas JavaScript objects can use either single or double quotes.
  • JSON does not allow functions, comments, or undefined values, all of which are permitted in JavaScript objects.
  • JSON keys must always be strings, but JavaScript object keys can be strings or identifiers.

Example of a Simple JSON Object

Here’s a basic example of a JSON object to illustrate the syntax:

{
        "name": "John",
        "age": 30,
        "isStudent": false,
        "skills": ["JavaScript", "HTML", "CSS"],
        "address": {
            "street": "123 Main St",
            "city": "Anytown",
            "zip": "12345"
        }
    }


Looking at the above example, here is a breakdown of some key features:

Key-Value Pairs: Each piece of data in the JSON object is presented as a key-value pair. For instance, "name": "John" pairs the key "name" with the value "John".

Data Types:

  • "name": A string value, "John", enclosed in double quotes.
  • "age": A number value, 30.
  • "isStudent": A boolean value, false, indicating that John is not a student.
  • "skills": An array of strings, ["JavaScript", "HTML", "CSS"], which lists John’s skills.
  • "address": A nested object that includes more key-value pairs related to John’s address.

Here is another example.  This time, the object represents a phone book with multiple records:

{
"phoneBook": [
{
"firstName": "John",
"lastName": "Doe",
"phone": "123-456-7890",
"email": "john.doe@example.com"
},
{
"firstName": "Jane",
"lastName": "Smith",
"phone": "987-654-3210",
"email": "jane.smith@example.com"
},
{
"firstName": "Michael",
"lastName": "Johnson",
"phone": "555-123-4567",
"email": "michael.johnson@example.com"
}
]
}


Valid Data Types in JSON

Understanding the valid data types that can be used in JSON is crucial for creating well-structured data:

Strings

Text enclosed in double quotes.

"example": "This is a string"

Numbers

Whole numbers or decimals (no quotes around numbers).

"price": 19.99

Objects

Collections of key-value pairs, enclosed in curly braces {}.

"user": {
"username": "jdoe",
"email": "jdoe@example.com"
}

Arrays

Lists of values, enclosed in square brackets []. The values can be any valid JSON data type.

"colors": ["red", "green", "blue"]

Booleans

true or false values.

"isAvailable": true

null

Represents an empty or non-existent value.

"middleName": null

Common Use Cases for JSON

JSON is used extensively in web applications, and understanding why it is so popular can help you appreciate its importance:

  1. Data Interchange: JSON is used to transfer data between a client (such as a web browser) and a server. For example, a web application might receive user data from a server in JSON format and display it on a webpage.
  2. APIs (Application Programming Interfaces): Most modern web APIs use JSON to format the data they send and receive. When you fetch data from an API, you are likely dealing with JSON.
  3. Configuration Files: JSON is often used in configuration files for applications, where settings need to be easily readable and modifiable.

Why JSON is So Popular

  • Human-Readable: JSON’s structure is simple and easy to understand, even for beginners.
  • Lightweight: JSON is compact, making it efficient to transfer over networks.
  • Language-Agnostic: JSON is not tied to JavaScript. It is supported by almost all modern programming languages, making it versatile for different software ecosystems.
  • Easy to Parse: JavaScript provides built-in methods for parsing JSON data, making it simple to work with in web applications.


Accessing JSON Data

The first step when working with JSON data is to understand how to access the information you need. In JavaScript, you can access data in a JSON object using dot notation or bracket notation.

Example JSON Object:

Here’s a simplified JSON object to illustrate the concepts

{
"firstName": "Alice",
"lastName": "Brown",
"email": "alice.brown@example.com",
"phone": "111-222-3333"
}

Accessing Values

Using dot notation:

let person = {
"firstName": "Alice",
"lastName": "Brown",
"email": "alice.brown@example.com",
"phone": "111-222-3333"
};

console.log(person.firstName); // Output: Alice
console.log(person.email); // Output: alice.brown@example.com

Using bracket notation:

console.log(person["lastName"]); // Output: Brown
console.log(person["phone"]); // Output: 111-222-3333

Both methods are useful, but dot notation is generally more readable and preferred unless the key name contains special characters or spaces.

Working with a JSON Dataset

When dealing with a dataset that contains multiple records, such as a JSON phone book, you will often use arrays to store each record. Here’s an example JSON phone book:

{
"phoneBook": [
{
"firstName": "John",
"lastName": "Doe",
"phone": "123-456-7890",
"email": "john.doe@example.com"
},
{
"firstName": "Jane",
"lastName": "Smith",
"phone": "987-654-3210",
"email": "jane.smith@example.com"
},
{
"firstName": "Michael",
"lastName": "Johnson",
"phone": "555-123-4567",
"email": "michael.johnson@example.com"
}
]
}

In JavaScript, you can access the data and loop through the records using a for loop.

Accessing Multiple Records Using a Loop

let phoneBook = {
"phoneBook": [
{
"firstName": "John",
"lastName": "Doe",
"phone": "123-456-7890",
"email": "john.doe@example.com"
},
{
"firstName": "Jane",
"lastName": "Smith",
"phone": "987-654-3210",
"email": "jane.smith@example.com"
},
{
"firstName": "Michael",
"lastName": "Johnson",
"phone": "555-123-4567",
"email": "michael.johnson@example.com"
}
]
};

// Loop through each record
phoneBook.phoneBook.forEach(record => {
console.log(`Name: ${record.firstName} ${record.lastName}`);
console.log(`Phone: ${record.phone}`);
console.log(`Email: ${record.email}`);
});


Modifying JSON Data

You can add, modify, or remove records from a JSON object in JavaScript. Let’s break down each operation.

Adding Records

To add a new record to a dataset that is an array of objects, use the push() method.

Example:

// Adding a new contact to the phone book
let newContact = {
"firstName": "Emily",
"lastName": "Clark",
"phone": "444-555-6666",
"email": "emily.clark@example.com"
};

phoneBook.phoneBook.push(newContact);

console.log(phoneBook.phoneBook);
// The new contact is now added to the phone book

Modifying Records

To modify an existing record, access the record by its index and update the necessary fields.

Example:

// Modifying the email address of the second contact
phoneBook.phoneBook[1].email = "jane.smith@newdomain.com";

console.log(phoneBook.phoneBook[1].email); // Output: jane.smith@newdomain.com

Removing Records

To remove a record from an array of objects, you can use the splice() method. The splice() method removes items from an array at a specified index.

Example:

// Removing the first contact from the phone book
phoneBook.phoneBook.splice(0, 1); // Removes 1 item at index 0

console.log(phoneBook.phoneBook);
// The first contact (John Doe) is now removed from the phone book


Methods for Working with JSON

JSON.parse()

Converts a JSON string into a JavaScript object. This is useful when you receive JSON data from an external source, such as a server or an API.

Example:

let jsonString = '{"name": "Anna", "age": 22}';
let jsonObject = JSON.parse(jsonString);
console.log(jsonObject.name); // Output: Anna

JSON.stringify()

Converts a JavaScript object into a JSON string. This is helpful when you want to prepare your data to be sent to a server or saved in a file.

Example:

let jsObject = { name: "Anna", age: 22 };
let jsonString = JSON.stringify(jsObject);
console.log(jsonString); // Output: '{"name":"Anna","age":22}'

Looping Through JSON Objects: Use a for...in loop or forEach() method to iterate through all keys or all records.

Example Using for...in Loop:

let person = { "name": "Liam", "age": 28, "email": "liam@example.com" };

for (let key in person) {
console.log(`${key}: ${person[key]}`);
}
// Output:
// name: Liam
// age: 28
// email: liam@example.com

Videos for Module 9 - JavaScript Object Notation (JSON)

There are no videos yet this term for this Module. Check back soon!

Activities for this Module

S9 - Displaying JSON Data

Note: Sandbox assignments are designed to be formative activities that are somewhat open-ended. To get the most value, spend some time playing around as you code.

Instructions:

JSON (JavaScript Object Notation) Data is a really powerful way to store data in JavaScript and to share it between applications. It is (relatively) easy to use, flexible, and organized. In this sandbox challenge, we are going to take some JSON-formatted data and display it on a Web Page using HTML, CSS and JavaScript.

Start out by downloading the sample JSON data file below. Save it in your  PHPStorm project directory, and open it up in PHP Storm. The first few lines should look like this:

[
  {
    "name": "Apples",
    "price": 1.50,
    "quantity": 12,
    "harvestDate": "2024-10-18"
  },
  {
    "name": "Oranges",
    "price": 1.20,
    "quantity": 8,
    "harvestDate": "2024-10-17"
  },

If you take a minute, you can see a pattern in how the data is put together. This pattern is what allows us to very easily access and read this data in a meaningful way using JavaScript. This challenge will walk you through the process of how that's done.

This data is structured in a format called JSON (JavaScript Object Notation). JSON is a way to store and organize data so that it can be easily read and used by programs. In JavaScript, it’s common to use JSON to represent a group of items with details for each item. 

Here’s a quick overview of how this data is organized:

Array of Items:

The entire data is an array (which you’re already familiar with) containing several items. Each item represents a type of fruit, like “Apples,” “Oranges,” or “Bananas.”

Objects Within the Array:

Each item in the array is stored as an object. Objects in JavaScript let us store multiple pieces of related information together. Instead of just a single value (like a number or string), each object here represents a specific fruit and includes several details about it, such as price, quantity, and harvest date.

Key-Value Pairs:

Inside each object, we have key-value pairs. This is a new concept but easy to understand:

  • A key is a name that describes a specific piece of information. Think of it like a label. For example, "name" is the key for the fruit’s name, "price" is the key for its price, and so on.
  • A value is the actual information associated with that key. So for "name": "Apples", "Apples" is the value that describes the name of the fruit.

Example Breakdown of a Single Object:

{
    "name": "Apples",
    "price": 1.50,
    "quantity": 12,
    "harvestDate": "2024-10-18"
}

This is one object in the array. Here:

  • "name" is the key, and "Apples" is the value.
  • "price" is the key, and 1.50 is the value.
  • "quantity" is the key, and 12 is the value.
  • "harvestDate" is the key, and "2024-10-18" is the value.

Why Use Key-Value Pairs?

By organizing data this way, we can quickly access specific details about each item. Instead of looking for “price” or “name” in a general list, we label each piece of data, making it easy to identify and retrieve the information we need.

JSON’s combination of arrays and objects with key-value pairs allows for a very organized structure, making data easy to manage, understand, and use in programs.

 

Next, download the S9 Template File below, and make sure you save it in the same directory in your project where you just placed the JSON file.  This is important, because if they aren't in the same directory then your script won't be able to find the JSON data.

Download the S9 Template File Download Download the S9 Template File

If you open the file, it will be pretty empty. That's because all of the real content for the file will be loaded from the JSON file and formatted on the fly using the CSS that is already in the document. Open the template, and let's get started:

Step 1:

First, we need to make a connection between our script and the JSON file. Add the following line of code inside the script tags:

fetch('fruitdata.json')

This code does just what you probably guessed - It retrieves the JSON file. The really cool thing about this fetch ( ) function is that it can be used to load data from another computer, a web server, or just about anywhere by just changing the string from a file name to an address online.  The downside to that is that if we are loading a large amount of data from a remote machine, it can sometimes take a bit, and that delay can cause issues or even errors in our code. Because of that, we need to use something called a "promise" – what this means is that we are going to tell JavaScript to split its attention; part of its focus will wait for the promise to be fulfilled (when the data loads), and part of the focus will go on listening for other events, etc. Let's add a promise to this fetch( ) function.

Step 2:

When we add a promise to this function, we are basically saying, "When that data loads, do this next..." Add the following line of code just below the fetch( ) function:

.then(response => response.json())

This line has two parts: The first is .then( ) which is the handler for the promise from the fetch( ) line above it. Inside the .then( ) is what happens when the data is loaded. In this part, the response (from the server, or in this case the local machine when it opens the file) is converted from binary text or regular text into JSON code that we can use.  The format is called an "arrow function". Don't worry too much about how they work for now. Just include the code as it is written.

Step 3:

The next line starts with another .then( ) – this is called promise chaining, and as you might have guessed, it means that the second .then( ) waits for the first one to complete, and then it takes its turn. This is another arrow function that takes the response as "data", and does something with it.  Here is the code for the next part, which should be added directly below the line you added in Step 2:

.then(data => {

});

Step 4:

The next few lines of code are all going to be added inside the block you added in Step 3, so make sure each line is placed between the { and });

In the next lines, there are two things happening:

  1. We are adding a variable reference to the fruitContainer div.
  2. We are beginning a loop to iterate through each object in the JSON data, and to do something with each one.

const container = document.getElementById('fruitContainer');
data.forEach(fruit => {

});

Make sure that whatever you do in the next few steps goes inside the { and }); for the forEach loop, so this code is run for each object in the data.

Step 5:

First, we need to create a new div element, and apply the "fruit-card" class to it. This code goes inside the forEach loop:

// Create fruit card
const card = document.createElement('div');
card.classList.add('fruit-card');

Step 6:

The following code should also go inside the forEach loop. In this step, we are adding the information from each JSON object to the "card" div.  Please take note of a few things about this code:

  • The ` characters are not single quotes ( ' ). This is the backtick character, often found to the left of the 1 key on a standard keyboard. In JavaScript, this has a special meaning, and defines something called a template literal, which is like a string but has some special abilities.
  • template literal can span multiple lines of code, and will keep that formatting.
  • template literal can inject the value of variables into the string output, by enclosing them in ${ and }.  For example, in the code below, you will see ${fruit.name} which will be interpreted by JavaScript to put the name of each fruit in that spot.  This is a handy way of inserting data or even the result of expressions into a string.

Here is the code to insert the template literal into the innerHTML property of the "card" div: 
** NOTE: This looks different, because Canvas keeps destroying my code so I had to use this format.

// Display information
card.innerHTML = `
        <h3>${fruit.name}</h3>
        <p>Price: $${fruit.price.toFixed(2)} each</p>
        <p class="quantity">${fruit.quantity} Available</p>
        <p>Harvest Date: ${fruit.harvestDate}</p>
    `;

Step 7:

This next bit of code also goes inside the forEach loop. After this addition, the remainder of the code will go after both the forEach loop and the .then (data => { section.

In this addition, we have two things happening:

  1. We are using the quantity of each fruit to determine the background color of the paragraph containing the quantity as a visual way of showing how much is left.
  2. Finally, we use .appendChild( ) to add the card inside the main container.

// Add color class based on quantity
const quantityElement = card.querySelector('.quantity');
if (fruit.quantity > 9) {
     quantityElement.classList.add('green');
} else if (fruit.quantity >= 5) {
     quantityElement.classList.add('yellow');
} else {
     quantityElement.classList.add('red');
}

// Add card to container
container.appendChild(card);

 Step 8:

 In this final step, you will add a last line to your script block, beneath both sets of });

This last line "catches" any kind of error if there is an error (such as, the script can't find the JSON file) and prints it to the console. This is good practice to include any time you are using any kind of promise, and especially if you are using promise chaining.

 .catch(error => console.error('Error loading fruit data:', error));

 When you have completed the script block, you should have the following. Only expand this and use it if you have tried doing it on your own and feel stuck. I did you a favor and at least hid it to start. 

A9 - Phone Book, Part 1

The Challenge

In this assignment, you will be building a functional contacts manager. This version will not save once you leave or refresh the page, but it will build a JSON data store as you add and modify records. I have given you a great starter file, which you need to complete in the following ways:

  1. Add two more "starter" records to the JSON data in the code.
  2. Complete the addContact function so that you can add records to the JSON object and then the change is reflected in the display.
  3. Complete the deleteContact function so that changes are reflected in the JSON and the display.
  4. Make whatever other enhancements or changes to the page that you'd like.

Here is the A9 Starter File

Constraints / Success Criteria

  • The page must be fully functional for adding and deleting records.
  • Use only what we have covered so far in this class.

How to Submit

Upload your HTML file.