Copyright Derek O'Reilly, Dundalk Institute of Technology (DkIT), Dundalk, Co. Louth, Ireland.
JSON (JavaScript Object Notation) allows data to be stored as a string. JSON holds data in a structured way. This structure is called a JSON object. A JSON object consists of a collection of key/value pairs that are contained inside {} brackets. The data that is held in a JSON object is called properties. Properties are separated by a , (comma), as shown below:
{key1:value1, key2:value2, key3:value3}
For example, use the JSON object below to hold to hold a name, phone and email:
{name:"Mary", phone:123456, email:"a@a.com"}
To make it more readable, JSON object code can be written over multiple lines, as shown below:
{ name:"Mary", phone:123456, email:"a@a.com" }
A JSON object can be assigned to a JavaScript variable.
let person = { name:"Anne", phone:123456, email:"a@a.com" }
To access a JSON object's property we use a "." (dot) between the object and its property. For example, we use the code below to access the name property of the person object:
person.name
Two {} hold an empty JSON object
let emptyJSONObject = {}
Arrow functions can return JSON objects. The JSON object needs to be wrapped in () parentheses.
const setDetails = (name, age) => ({name: name, age: age}) let details = setDetails("Mary", 20) console.log(`${details.name} ${details.age}`)
JSON data can be held in an array. We use [] brackets to structure JSON arrays, as shown below:
people = [ {name:"Anne", phone:1111, email:"a@a.com"}, {name:"Brian", phone:2222, email:"b@b.com"}, {name:"Cathy", phone:3333, email:"c@c.com"} ] // or more commonly, we compact the [] brackets, as shown below people = [{name:"Anne", phone:1111, email:"a@a.com"}, {name:"Brian", phone:2222, email:"b@b.com"}, {name:"Cathy", phone:3333, email:"c@c.com"}]
To access an element in the array, we use an array index, as shown below:
people = [{name:"Anne", phone:1111, email:"a@a.com"}, {name:"Brian", phone:2222, email:"b@b.com"}, {name:"Cathy", phone:3333, email:"c@c.com"}] console.log(`First element of array is:`, people[0]) console.log(`Email of second person in array is:`, people[1].email)
We can loop through a JSON array using a forEach function, as shown below:
people = [{name:"Anne", phone:1111, email:"a@a.com"}, {name:"Brian", phone:2222, email:"b@b.com"}, {name:"Cathy", phone:3333, email:"c@c.com"}] people.forEach((person, index) => console.log(`Person ${index} name is: ${person.name}`))
Two [] brackets hold an empty JSON array
let emptyJSONArray = []
Normal arrays are valid JSON structures, as shown below:
let jsonStringArray = ["Alan", "Brian", "Colm"] let jsonNumberArray = [4, 25, 15, 100]
Several functions are available that allow us to manipulate the data in a JSON array.
The map() function allows us to run the same function against each item in a JSON array.
The map() function is immutable, which means that it does not change the content of the original array that is being mapped.
Example of map() function (Run example)
<!DOCTYPE html> <html> <head> <title>JSON array map() example</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script> let employees = [{forename:"Ann", surname:"Anglesey", role:"IT"}, {forename:"Brian", surname:"Brown", role:"HR"}, {forename:"Cathy", surname:"Connolly",role:"HR"}, {forename:"Dennis", surname:"Doherty", role:"IT"}, {forename:"Emma", surname:"Eagan", role:"HR"} ] /* Combine forename and surname into a string and save to an array */ let fullnameArray = employees.map(employee => `${employee.forename} ${employee.surname}`) console.log(`Array of strings`) console.log(fullnameArray) /* New JSON array object with only forename and surname */ let fullnameJSON = employees.map(employee => ({forename:employee.forename, surname:employee.surname})) console.log(`Array of JSON objects`) console.log(fullnameJSON) </script> </head> <body> <div>View the console output in browser's Web DevTools (F12)</div> </body> </html>
A for-loop can achieve the same outcome as a map() function. The difference is that a for-loop requires more code.
Example of a for-loop replacing a map() function (Run Example)
<!DOCTYPE html> <html> <head> <title>JSON for-loop replacing map() example</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script> let employees = [{forename:"Ann", surname:"Anglesey", role:"IT"}, {forename:"Brian", surname:"Brown", role:"HR"}, {forename:"Cathy", surname:"Connolly",role:"HR"}, {forename:"Dennis", surname:"Doherty", role:"IT"}, {forename:"Emma", surname:"Eagan", role:"HR"} ] // let fullnameArray = employees.map(employee => employee.forename + " " + employee.surname) // the code below is the for-loop equivalent of the above map() let fullnameArray = [] for(let i = 0; i < employees.length; i++) { fullnameArray[i] = employees[i].forename + " " + employees[i].surname } console.log(`Array of strings`) console.log(fullnameArray) // let fullnameJSON = employees.map(employee => ({forename:employee.forename, surname:employee.surname})) // the code below is the for-loop equivalent of the above map() let fullnameJSON = [] for(i = 0; i < employees.length; i++) { fullnameJSON[i] = {forename:employees[i].forename, surname:employees[i].surname} } console.log(`Array of JSON objects`) console.log(fullnameJSON) </script> </head> <body> <div>View the console output in browser's Web DevTools (F12)</div> </body> </html>
The filter() function creates a new array that contains all elements from the original array that pass the logical conditional that is contained within the filter() function.
The filter() function is immutable, which means that it does not change the content of the original array that is being mapped.
An example of filter() applied to an array of objects (Run Example)
<!DOCTYPE html> <html> <head> <title>JSON array filter() example</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script> let employees = [{name:"Ann", role:"IT", salary:100000}, {name:"Brian", role:"HR", salary:50000}, {name:"Cathy", role:"HR", salary:60000}, {name:"Dennis", role:"IT", salary:120000}, {name:"Emma", role:"HR", salary:30000}] let hrEmployees = employees.filter(employee => employee.role === "HR") console.log(`All Employees`) console.log(employees) console.log(`HR Employees`) console.log(hrEmployees) </script> </head> <body> <div>View the console output in browser's Web DevTools (F12)</div> </body> </html>
A for-loop can be used to replace the filter() function. Write code to do this.
The reduce() function reduces an array to a single value. This value is the result of applying a given function against an accumulator and each element in the array (from left to right). The accumulator must be set with an initial value. In the examples below, the variable total is the accumulator. In the example below the accumulator is called total and it has been initialised to 0.
The reduce() function is immutable, which means that it does not change the content of the original array that is being mapped.
An example of reduce() applied to an array of objects (Run Example)
<!DOCTYPE html> <html> <head> <title>JSON array reduce() example</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script> let employees = [{name:"Ann", role:"IT", salary:100000}, {name:"Brian", role:"HR", salary:50000}, {name:"Cathy", role:"HR", salary:60000}, {name:"Dennis", role:"IT", salary:120000}, {name:"Emma", role:"HR", salary:30000}] let totalSalary = employees.reduce((total, employee) => total += employee.salary, 0) console.log(`Total salary is: ${totalSalary}`) </script> </head> <body> <div>View the console output in browser's Web DevTools (F12)</div> </body> </html>
A for-loop can be used to replace the reduce() function. Write code to do this.
Adjust the example code given above and output the mean average salary for each of IT, HR and for all employees, as shown here.
The some() function will return true if at least one item in the array matches a given condition.
The some() function is immutable, which means that it does not change the content of the original array that is being mapped.
An example of some() applied to an array of objects (Run Example)
<!DOCTYPE html> <html> <head> <title>JSON array some() example</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script> let employees = [{forename:"Ann", surname:"Anglesey", role:"IT"}, {forename:"Brian", surname:"Brown", role:"HR"}, {forename:"Cathy", surname:"Connolly",role:"HR"}, {forename:"Dennis", surname:"Doherty", role:"IT"}, {forename:"Emma", surname:"Eagan", role:"HR"} ] let objectContainsName = employees.some(employee => employee.forename === "Cathy") console.log(objectContainsName) // will display true, as the name "Cathy" occurs at least once in the object </script> </head> <body> <div>View the console output in browser's Web DevTools (F12)</div> </body> </html>
Adjust the code above and test against the forename "Murphy". You should get false as the console output.
The every() function will return true if all of the items in the array matches a given condition.
The every() function is immutable, which means that it does not change the content of the original array that is being mapped.
An example of every() applied to an array of objects (Run Example)
<!DOCTYPE html> <html> <head> <title>JSON array every() example</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script> let employees = [{forename:"Ann", surname:"Anglesey", role:"IT", salary:100000}, {forename:"Brian", surname:"Brown", role:"HR", salary:30000}, {forename:"Cathy", surname:"Connolly",role:"HR", salary:50000}, {forename:"Dennis", surname:"Doherty", role:"IT", salary:150000}, {forename:"Emma", surname:"Eagan", role:"HR", salary:40000}] let minSalaries = employees.every(employee => employee.salary > 10000) console.log(minSalaries) // will display true, as all of the salaries are at least 10000 </script> </head> <body> <div>View the console output in browser's Web DevTools (F12)</div> </body> </html>
Adjust the code above and test against a salary > 100000. You should get false as the console output.
If we assign a new variable to an JSON array, the new variable will point to the exact same array. Any manipulation of the new array will cause the original array's data to also change. If we want to leave an origional JSON array unchanged, then we must make a new copy of the JSON array. We can use the spread operator to make the new copy of the JSON array, as shown in the code below:
// Make a copy of origianlJSONArray and place the new data in copyOfJSONArray let copyOfJSONArray = [...origianlJSONArray]
Use the inline function below to sort object arrays. A sort can be based on either a string or numerical value.
This function is mutable. It will change the original array.
An example sorting of an array of objects (Run Example)
<!DOCTYPE html> <html> <head> <title>JSON array sort() example</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script> let arrayOfObjects = [{name: "Cathy", age: 25}, {name: "Anne", age: 22}, {name: "Dermot", age: 20}, {name: "Bill", age: 21}, {name: "Eric", age: 19}] // sort by string let ascendingOrderByName = [...arrayOfObjects] ascendingOrderByName.sort((a, b) => a.name < b.name?-1:1) let descendingOrderByName = [...arrayOfObjects] descendingOrderByName.sort((a, b) => a.name < b.name?1:-1) // sort by number let ascendingOrderByAge = [...arrayOfObjects] ascendingOrderByAge.sort((a, b) => a.age < b.age?-1:1) let descendingOrderByAge = [...arrayOfObjects] descendingOrderByAge.sort((a, b) => a.age < b.age?1:-1) console.log(`Original data:`) console.log(arrayOfObjects) console.log(`Ascending order by name:`) console.log(ascendingOrderByName) console.log(`Descending order by name:`) console.log(descendingOrderByName) console.log(`Ascending order by age:`) console.log(ascendingOrderByAge) console.log(`Descending order by age:`) console.log(descendingOrderByAge) </script> </head> <body> <div>View the console output in browser's Web DevTools (F12)</div> </body> </html>
It is common to display a JSON array on a webpage. This can be done using a for-loop and document.getElementById().innerHTML
Example showing document.getElementById().innerHTML (Run Example)
<!DOCTYPE html> <html> <head> <title>JSON array as an unformatted table Example</title> <script> let cars = [ { model: "avensis", colour: "red", year: 2017, price: 35000 }, { model: "yaris", colour: "white", year: 2015, price: 1000 }, { model: "corolla", colour: "white", year: 2017, price: 20000 }, { model: "avensis", colour: "red", year: 2015, price: 15000 }, { model: "corolla", colour: "black", year: 2010, price: 4000 } ] function viewJSONData() { let htmlString = `<table>` cars.forEach(car => { htmlString += `<tr> <td>${car.model}</td> <td>${car.colour}</td> <td>${car.year}</td> <td>${car.price}</td> </tr>` }) htmlString += `</table><br> ${cars.length} items found.` document.getElementById("cars").innerHTML = htmlString } </script> </head> <body onload="viewJSONData()"> <div id = "cars">Car details will be listed here.</div> </body> </html>
Change the above code so that CSS styling is applied to the table, as shown here.
Change the code above to display the output as an ordered list instead of a table, as shown here.
The Object.keys() method returns an array containing all of an object's property keys (from the key:value pair). The keys are stored in the array as a list of strings. The keys will be stored in the array in the same order that they occur in the JSON object.
let employees = {forename:"Ann", surname:"Anglesey", role:"IT"} console.log(Object.keys(employees)) // output will be ["forename", "surname", "role"]
We can use a JSON property's key to access a property's value. In the example below, we access the value of the surname key.
let employees = {forename:"Ann", surname:"Anglesey", role:"IT"} console.log(employees["surname"]) // will output "Anglesey"
[{forename: "Ann", surname: "Connolly", role: "IT", salary: 50000}, {forename: "Dennis", surname: "Brown", role: "IT", salary: 45000}, {forename: "Cathy", surname: "Eagan", role: "HR", salary: 55000}, {forename: "Brian", surname: "Anglesey", role: "Accounts", salary: 5000}, {forename: "Emma", surname: "Doherty", role: "HR", salary: 60000}]Using the Object.keys() method, write code to display a table containing all of the data in the JSON array above, as shown here.You should use the Object.keys() method to get the table column names and the cell data.
[{forename: "Ann", surname: "Connolly", role: "IT", salary: 50000, gender:"female"}, {forename: "Dennis", surname: "Brown", role: "IT", salary: 45000, gender:"male"}, {forename: "Cathy", surname: "Eagan", role: "HR", salary: 55000, gender:"female"}, {forename: "Brian", surname: "Anglesey", role: "Accounts", salary: 5000, gender:"male"}, {forename: "Emma", surname: "Doherty", role: "HR", salary: 60000, gender:"female"}]Add a gender propperty to the JSON array, as shown in the JSON array above. The amended table should display, as shown here.
[{forename: "Ann", surname: "Connolly", role: "IT", salary: 50000, gender:"female"}, {forename: "Dennis", surname: "Brown", role: "IT", salary: 45000, gender:"male"}, {forename: "Cathy", surname: "Eagan", role: "HR", salary: 55000, gender:"female"}, {forename: "Brian", surname: "Anglesey", role: "Accounts", salary: 5000, gender:"male"}, {forename: "Emma", surname: "Doherty", role: "HR", salary: 60000, gender:"female"}]Given the JSON data above:Write code to allow a user to sort the data by forename, surname, role, salary or gender. The user should be able to sort the data in both assending and descending order, as shown here.
Adjust the code above to include an arrow to indicate the sort direction, as shown here.
Adjust the code above to allow the user to search for any text that occurs in a forename or surname, as shown here.
Adjust the code above to allow the user to include checkboxes that filter the displayed data against the employee role. You must dynamically obtain the set of roles from the JSON, so that it will work for any set of roles, as shown here.
Adjust the code above to allow the user to include checkboxes that filter the displayed data against the employee role and gender, as shown here.
Adjust the code above so that all checkboxes being empty for either role or gender will result in that filter not being applied, as shown here.
Adjust the code above so that the table columns that are to be filtered are stored in an array of JSON objects, as shown here. Based on the array of JSON objects, the set of checkboxes that is displayed and the filtering of these checkboxes should be done automatically. The array structure should be [{name:"role", checkboxes:uniqueRoles}, {name:"gender", checkboxes:uniqueGenders}], where role and gender are the table columns that we want to use checkboxes to filter and uniqueRoles and uniqueGenders are the checkboxes (such as IT, HR, et cetera).
To test your code, add a nationality property to the JSON array (to give the JSON data below). Your code should automatically update the set of checkboxes and automatically filter the displayed checkboxes, as shown here.
[{forename: "Ann", surname: "Connolly", role: "IT", salary: 50000, gender: "female", nationality: "EU"}, {forename: "Dennis", surname: "Brown", role: "IT", salary: 45000, gender: "male", nationality: "EU"}, {forename: "Cathy", surname: "Eagan", role: "HR", salary: 55000, gender: "female", nationality: "EU"}, {forename: "Brian", surname: "Anglesey", role: "Accounts", salary: 5000, gender: "male", nationality: "UK"}, {forename: "Emma", surname: "Doherty", role: "HR", salary: 60000, gender: "female", nationality: "USA"}]
Adjust the code above so that the list of column names to be included in the table is stored in an array, as shown here.
The Object.keys() method can be used for validation. If a set of individual validation tests are stored in a JSON, then the Object.keys() method can be used to test if all the validation tests have been passed.
let validationTests = {name: true, address: false, age: true, phone: true}
let passedAllTests = Object.keys(validationTests).every(key => validationTests[key] === true)
document.write(`Output is `, passedAllTests) // output is false
Given the JSON list {name:true, address:false, age:true, phone:true}, which contains a set of properties that are each set to true or false, write code to detect if all property has been set to "true", as shown here.
A JSON structure can contain other JSON structures.
In the example below, the top-level JSON object contains a name, description and rounds property.
The rounds array contains a JSON object, which has the properties name and questions.
The questions array contains a JSON object, which has the properties, text, correct and choices.
Example showing nested JSON (Run Example)
<!DOCTYPE html> <html> <head> <title>Nested JSON object example</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script> countryQuizData = { name: "Countries Quiz", description: "EU and other countries quiz", rounds: [ { name: "The EU", questions: [ { text: "How many countries are there in the EU?", correct: 1, choices: [ "26", "27", "28" ] }, { text: "Which EU country has the largest population?", correct: 1, choices: [ "France", "Germany" ] }, { text: "Which EU country has the smallest population?", correct: 2, choices: [ "Luxemburg", "Cyprus", "Malta" ] }, { text: "What is the approximate population of the EU?", correct: 1, choices: [ "400 million", "450 million", "500 million", "550 million", "600 million" ] } ] }, { name: "World Wide", questions: [ { text: "Which country has the largest population?", correct: 2, choices: [ "Russia", "India", "China", "USA" ] }, { text: "Which country occupies the largest area?", correct: 0, choices: [ "Russia", "India", "China" ] } ] } ] } function viewJSONData() { let htmlString = `countryQuizData.rounds[0].questions[1].text is ${countryQuizData.rounds[0].questions[1].text}
countryQuizData.rounds[0].questions[1].choices[0] is ${countryQuizData.rounds[0].questions[1].choices[0]}
countryQuizData.rounds[0].questions[1].choices[1] is ${countryQuizData.rounds[0].questions[1].choices[1]}
The correct answer is ${countryQuizData.rounds[0].questions[1].choices[countryQuizData.rounds[0].questions[1].correct]}` document.getElementById("quiz").innerHTML = htmlString } </script> </head> <body onload="viewJSONData()"> <div id = "quiz"></div> </body> </html>
As shown in the above example, JSON arrays can be of different lengths. For example, round 1 has four questions and round 2 has two questions.
The code below shows how we can use a JSON object's property to be an index into a JSON array.
htmlString += `The correct answer is <strong>${countryQuizData.rounds[0].questions[1].choices[countryQuizData.rounds[0].questions[1].correct]}</strong>`
Write code to show all of the questions and possible answers in the quiz, as shown here. Use forEach() rather than for-loops.
Write code that replaces each forEach() in the code above with a for-loop, as shown here.
The above two questions show that, when using nested JSON objects, it is much easier to write and understand the code if we use forEach() rather than a for-loop
// forEach() function viewJSONData() { let htmlString = `<ul>` countryQuizData.rounds.forEach(round => { htmlString += `<li>${round.name}</li>` htmlString += `<ul>` round.questions.forEach(question => { htmlString += `<li>${question.text}</li>` htmlString += `<ul>` question.choices.forEach(choice => { htmlString += `<li>${choice}</li>` }) htmlString += `</ul>` }) htmlString += `</ul>` }) htmlString += `</ul>` document.getElementById(`quiz`).innerHTML = htmlString } // for-loop function viewJSONData() { let htmlString = `<ul>` for(let round = 0; round < countryQuizData.rounds.length; round++) { htmlString += `<li>${countryQuizData.rounds[round].name}</li>` htmlString += `<ul>` for(let question = 0; question < countryQuizData.rounds[round].questions.length; question++) { htmlString += `<li>${countryQuizData.rounds[round].questions[question].text}</li> <ul>` for(let choice = 0; choice < countryQuizData.rounds[round].questions[question].choices.length; choice++) { if(choice === countryQuizData.rounds[round].questions[question].correct) { htmlString += `<span style='color:redfont-weight:bold'>` } htmlString += `<li>${countryQuizData.rounds[round].questions[question].choices[choice]}</li>` if(choice === countryQuizData.rounds[round].questions[question].correct) { htmlString += `</span>` } } htmlString += `</ul>` } htmlString += `</ul>` } htmlString += `</ul>` document.getElementById("quiz").innerHTML = htmlString }
Once we know how to access the data at the different levels of a nested JSON object, we can write more complicated code, such as in the questions below:
Adjust the code above to show all of the questions and possible answers in the quiz. The correct answer should be highlighted for each question, as shown here. Hint: You need to use the forEach() function's optional index parameter. In your code, you can identify if the answer is correct by comparing forEach()'s index against the question's correct property value.
Write code to allow a user to answer each of the questions in the quiz. The user should be given their score when they finish the quiz, as shown here.
Tabular data can be stored as two arrays inside a JSON object. One array will hold the property keys (table column headings) and the second array can hold the property values (table rows data). For example, consider the tablular data below:
Country | Capital | Population |
---|---|---|
Ireland | Dublin | 5000000 |
France | Paris | 65000000 |
Poland | Warsaw | 38000000 |
Using key/value pairs, we can store this data in the JSON object below:
countryData = [ { name: "Ireland", capital: "Dublin", population: 5000000 }, { name: "France", capital: "Paris", population: 65000000 }, { name: "Poland", capital: "Warsaw", population: 38000000 } ]
Because it is tabular, we can also store this data in a JSON object that has two arrays, one each for the keys and values, as shown below:
countryData = { keys: ["Name", "Capital City","Population"], values: [ ["Ireland", "Dublin", 5000000], ["France", "Paris", 65000000], ["Poland", "Warsaw", 38000000] ] }
The keys array and and each of the values arrays MUST have the same number of elements (in the above case, three elements).
The tabular data arrays do not always have to be called keys and values. They can be any names that are appropriate for the given data.
To access a specific key/value pair from the JSON data above, we assign a constant to identify the index of each key/value
countryData = { keys: ["Name", "Capital City","Population"], values: [ ["Ireland", "Dublin", 5000000], ["France", "Paris", 65000000], ["Poland", "Warsaw", 38000000] ] } const NAME = 0, CAPITAL = 1, POPULATION = 2
The code below allows us to access the three keys
countryData.keys[NAME] countryData.keys[CAPITAL] countryData.keys[POPULATION]
The code below allows us to access the three values of the first country (which has index 0)
countryData.values[0][NAME] countryData.values[0][CAPITAL] countryData.values[0][POPULATION]
Normally, we would loop through the values to produce some kind of tabular output. The example below shows how we do this.
Example of tabular data being held in a JSON object (Run Example)
<!DOCTYPE html> <html> <head> <title>JSON Tabular data example</title> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <meta http-equiv="Content-Language" content="en" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> #countriesTable { width:250px; margin-left:auto; margin-right:auto; border-collapse:collapse; } #countriesTable th { text-align: left; background-color:#aaa; color:#fff; } #countriesTable th, #countriesTable td { padding:5px; } #countriesTable .population { text-align:right; } #countriesTable tbody { border:thin solid #aaa; } #countriesTable tbody tr:nth-child(odd) { background-color: #ffa; } .right_align { text-align: right !important; } </style> <script> function showCountriesTable() { countryData = { keys: ["Name", "Capital City","Population"], values: [ ["Ireland", "Dublin", 5000000], ["France", "Paris", 65000000], ["Poland", "Warsaw", 38000000] ] } const NAME = 0, CAPITAL = 1, POPULATION = 2 let innerHTML = `<table id="countriesTable"> <tr> <th>${countryData.keys[NAME]}</th> <th>${countryData.keys[CAPITAL]}</th> <th class="right_align">${countryData.keys[POPULATION]}</th> </tr>` countryData.values.forEach(country => innerHTML += `<tr> <td>${country[NAME]}</td> <td>${country[CAPITAL]}</td> <td class="right_align">${country[POPULATION]}</td> </tr>`) innerHTML += `</table>` document.getElementById("countries").innerHTML = innerHTML } </script> </head> <body onload='showCountriesTable()'> <div id='countries'></div> </body> </html>
We can hold both key/value data and tabular array data in the same JSON object. In the example below, modules and moduleGrades hold the tabular data keys and values arrays, while name and id hold normal key/value data.
In this example, the modules array and each of the moduleGrades arrays hold three elements.
studentsData = { modules: ["Programming", "Mathematics", "Web"], students: [ { name: "Colm", id: 3333, moduleGrades: [65, 45, 70] }, { name: "Grace", id: 6666, moduleGrades: [37, 39, 44] }, { name: "Deirdre", id: 4444, moduleGrades: [80, 85, 82] }, { name: "Brian", id: 2222, moduleGrades: [30, 45, 40] }, { name: "Francis", id: 5555, moduleGrades: [40, 50, 44] }, { name: "Anne", id: 1111, moduleGrades: [70, 85, 90] } ] }
Given the JSON data above, write code (as shown here) to allow a user to:
Write code to improve the visual user-interface of the above example.
The filter() function can be used to search for one or more elements in an JSON array.
The code below will return an JSON array that contains all of the cars that match the search colour.
function searchCarsByColour(colour) { const selectedCars = cars.filter(car => car.colour === colour) return selectedCars } // Example let selectedCars = searchCarsByColour("Red")
The code below will return the one element that matches the search id
function searchCarsByID(id) { const selectedCars = cars.filter(car => car.id === id) return selectedCars[0] } // Example let selectedCar = searchCarsByID(4)
The filter() function returns an array. However, as we are searching aginast a unique id, we know that there will only be a match for one element. Therefore, the first element in the selectedCars array - selectedCars[0] - will contain the one matched element.
Use the push() function to add an element to any array. The code below will add a new car JSON object to a cars JSON array.
function addCar(model, colour, year, price) { let newCar = {model:model, colour:colour, year:year, price:price} cars.push(newCar) } // Example addCar("Avensis", "Red", 2020, 15000)
We often need to include a unique id for each element in a JSON array. The code below will add a car with a unique id to a JSON array of cars.
function addCar(model, colour, year, price) { let newCar = {id:uniqueId, model:model, colour:colour, year:year, price:price} cars.push(newCar) uniqueId++ } // Example addCar("Avensis", "Red", 2020, 15000)
Assuming that uniqueId was unique before calling the function, we use the uniqeId for this element and then increment uniqueId, so that it will be a new unique number the next time we go to add another new element.
In order to modify an element, we need to be able identify that element. We can use the element's id to do this.
We can use the forEach() function to step through all of the elements in the array. Inside the forEach(), we can use an if statement to match against the element that we want to modify. We can then replace this elements details with the new, modified, details.
function modifyCar(id, model, colour, year, price) { cars.forEach(car => { if(car.id === id) { car.model = model car.colour = colour car.year = year car.price = price } }) } // Example updateCar(4, "Corolla", "Silver", 2020, 10000)
In order to delete an element, we need to be able identify that element. We can use the element's id to do this.
We can use the forEach() function to step through all of the elements in the array. Inside the forEach(), we can use an if statement to match against the element that we want to delete. Within the if statement can note the index in the array of the element that we want to delete. We shall store this index in selectedIndex. Finally, we use the splice() function to delete the selectedIndex element from the array.
function deleteCar(id) { let selectedIndex cars.forEach((car, index) => { if(car._id === id) { selectedIndex = index } }) cars.splice(selectedIndex, 1) } // Example deleteCar(4)
The second parameter in the splice() function is the number of elements that we want to delete. In this case, we want to delete 1 element.
Write code to allow a user to search by id, search by model, add, modify and delete cars from a JSON array, as shown here.
Copyright Derek O' Reilly, Dundalk Institute of Technology (DkIT), Dundalk, Co. Louth, Ireland.