Table of Contents
When it comes to storing, retrieving, or transmitting data, there are a bunch of file formats and data structures that you can use. You've probably used text files, Word documents, Excel spreadsheets, zip files, and so on to deal with the various kinds of data you handle. On the web front, there is one format that reigns supreme over all others. It runs faster. It jumps higher. It has a shinier (and furrier) coat of fur. That format is known as JSON - short for JavaScript Object Notation.
In this article, we are going to learn all about what makes JSON objects awesome. We'll look in detail at what goes inside them and how you can read values from them as part of your own implementations.
Onwards!
In JavaScript, you have a way of defining objects using the object literal syntax:
let funnyGuy = {
firstName: "Conan",
lastName: "O'Brien",
getName: function () {
return "Name is: " + this.firstName + " " + this.lastName;
}
};
let theDude = {
firstName: "Jeffrey",
lastName: "Lebowski",
getName: function () {
return "Name is: " + this.firstName + " " + this.lastName;
}
};
let detective = {
firstName: "Adrian",
lastName: "Monk",
getName: function () {
return "Name is: " + this.firstName + " " + this.lastName;
}
};
If you aren't familiar with this syntax, I highly recommend you read more about it in the Deeper Look at Objects article. It will make understanding and working with JSON objects significantly easier!
On the surface, the object literal syntax looks like a bunch of brackets and colons and weird curly braces that define your object's properties and values. Despite how weird it looks, under the covers, it is fairly descriptive. Many of the common data types you would want to use are available. You can neatly represent their properties and values as key and value pairs separated by a colon. Equally important as all the other stuff I just mentioned, this syntax allows you to have structure and nested values. Overall, it is a pretty sweet way of representing JavaScript objects...in a literal representation!
The JSON format borrows heavily from this object literal syntax. Here is an example of some honest-to-goodness real JSON data returned by the WeatherUnderground API for displaying the weather in my hometown of Seattle:
{
"response": {
"version": "0.1",
"termsofService": "http://www.wunderground.com/weather/api/d/terms.html",
"features": {
"conditions": 1
}
},
"current_observation": {
"image": {
"url": "http://icons.wxug.com/graphics/wu2/logo_130x80.png",
"title": "Weather Underground",
"link": "http://www.wunderground.com"
},
"display_location": {
"full": "Seattle, WA",
"city": "Seattle",
"state": "WA",
"state_name": "Washington",
"country": "US",
"country_iso3166": "US",
"zip": "98101",
"magic": "1",
"wmo": "99999",
"latitude": "47.61167908",
"longitude": "-122.33325958",
"elevation": "63.00000000"
},
"observation_location": {
"full": "Herrera, Inc., Seattle, Washington",
"city": "Herrera, Inc., Seattle",
"state": "Washington",
"country": "US",
"country_iso3166": "US",
"latitude": "47.616558",
"longitude": "-122.341240",
"elevation": "121 ft"
},
"estimated": {},
"station_id": "KWASEATT187",
"observation_time": "Last Updated on August 28, 9:28 PM PDT",
"observation_time_rfc822": "Fri, 28 Aug 2015 21:28:12 -0700",
"observation_epoch": "1440822492",
"local_time_rfc822": "Fri, 28 Aug 2015 21:28:45 -0700",
"local_epoch": "1440822525",
"local_tz_short": "PDT",
"local_tz_long": "America/Los_Angeles",
"local_tz_offset": "-0700",
"weather": "Overcast",
"temperature_string": "68.0 F (20.0 C)",
"temp_f": 68.0,
"temp_c": 20.0,
"relative_humidity": "71%",
"wind_string": "Calm",
"wind_dir": "NNW",
"wind_degrees": 331,
"wind_mph": 0.0,
"wind_gust_mph": "10.0",
"wind_kph": 0,
"wind_gust_kph": "16.1",
"pressure_mb": "1008",
"pressure_in": "29.78",
"pressure_trend": "-",
"dewpoint_string": "58 F (15 C)",
"dewpoint_f": 58,
"dewpoint_c": 15,
"heat_index_string": "NA",
"heat_index_f": "NA",
"heat_index_c": "NA",
"windchill_string": "NA",
"windchill_f": "NA",
"windchill_c": "NA",
"feelslike_string": "68.0 F (20.0 C)",
"feelslike_f": "68.0",
"feelslike_c": "20.0",
"visibility_mi": "10.0",
"visibility_km": "16.1",
"solarradiation": "--",
"UV": "0",
"precip_1hr_string": "0.00 in ( 0 mm)",
"precip_1hr_in": "0.00",
"precip_1hr_metric": " 0",
"precip_today_string": "0.00 in (0 mm)",
"precip_today_in": "0.00",
"precip_today_metric": "0",
"icon": "cloudy",
"icon_url": "http://icons.wxug.com/i/c/k/nt_cloudy.gif",
"nowcast": ""
}
}
Ignoring the size of the data returned, there are a lot of similarities between the JSON data you see and the object literal syntax you saw earlier. There are some major differences that you need to be aware of as well, but we'll look at all that boring stuff later. First, let's take a deeper look at what exactly makes up a JSON object.
A JSON object is nothing more than a combination of property names and their values. That seems pretty simple, but there are some important details that we need to go over in this section.
Property names are the identifiers you will use to access a value. Visually, they are the things to the left of the colon character:
{
"firstName": "Kirupa",
"lastName": "Chinnathambi",
"special": {
"admin": true,
"userID": 203
},
"devices": [
{
"type": "laptop",
"model": "Macbook Pro 2015"
},
{
"type": "phone",
"model": "iPhone 6"
}
]
}
In this JSON snippet, the property names are firstName, lastName, special, admin, userID, devices, type, and model. Notice how the property names are defined. They are string values wrapped in quotation marks. The quotation mark is an important detail that you don't have to specify in the object literal case for property names, so don't forget to include them when working in the JSON world!
Each property name maps to a value, and the types of values you can have are:
Let's map these various types to the example we just looked at earlier.
The string values are the following highlighted lines:
{
"firstName": "Kirupa",
"lastName": "Chinnathambi",
"special": {
"admin": true,
"userID": 203
},
"devices": [
{
"type": "laptop",
"model": "Macbook Pro"
},
{
"type": "phone",
"model": "iPhone XS"
}
]
}
The double quotation marks are a dead giveaway that these values are strings. Besides your usual letters and numbers and symbols, you can also include escape characters like \', \", \\, \/, and so on to define characters in your string that would otherwise get parsed as some JSON operation.
Our lone representative of the number family is the value for the userID property:
{
"firstName": "Kirupa",
"lastName": "Chinnathambi",
"special": {
"admin": true,
"userID": 203
},
"devices": [
{
"type": "laptop",
"model": "Macbook Pro"
},
{
"type": "phone",
"model": "iPhone XS"
}
]
}
You can specify both decimal values (eg: 0.204, 1200.23, 45) as well as exponential values (2e16, 3e+4, 1.5e-2). There are some quirks you need to be aware of, though. You can't prefix your number with a 0 followed by another number. For example, a value of 03.14 isn't allowed.
Boolean values are easy:
{
"firstName": "Kirupa",
"lastName": "Chinnathambi",
"special": {
"admin": true,
"userID": 203
},
"devices": [
{
"type": "laptop",
"model": "Macbook Pro"
},
{
"type": "phone",
"model": "iPhone XS"
}
]
}
The values can either be true or false. One thing to note - the capitalization is important. Both true and false have to be lowercase. Using sentence casing (True or False) or going with all caps (TRUE or FALSE) is forbidden.
This is where things get a little interesting:
{
"firstName": "Kirupa",
"lastName": "Chinnathambi",
"special": {
"admin": true,
"userID": 203
},
"devices": [
{
"type": "laptop",
"model": "Macbook Pro"
},
{
"type": "phone",
"model": "iPhone XS"
}
]
}
Objects contain a collection of property names and values, and they are separated from the rest of your content with curly brackets. See? Wasn't that a little interesting?
Our devices property represents an array:
{
"firstName": "Kirupa",
"lastName": "Chinnathambi",
"special": {
"admin": true,
"userID": 203
},
"devices": [
{
"type": "laptop",
"model": "Macbook Pro"
},
{
"type": "phone",
"model": "iPhone XS"
}
]
}
Arrays store an ordered collection of zero or more values that you can iterate through, and they are separated by the bracket notation. Inside an array, you can use any of the JSON types we've seen so far...including other arrays!
The last data type is also the most boring one:
{
"foo": null
}
Your JSON values can be null. This represents an empty value.
I admit it. The previous section was extremely dull, but there is some good news! Given how boring what you just saw was, this section is by comparison going to seem a whole lot more exciting than it really is. Yay!
Anyway, almost all of your interactions with JSON will revolve around reading data. When it comes to reading JSON data, the main thing to keep in mind is that it is very similar to reading values stored inside a typical JavaScript Object. You can either dot into the value you want (property.propertyFoo) or you can use the array approach (property["propertyFoo"]) and access the value that way.
To help explain all this, let's use the following example:
let exampleJSON = {
"firstName": "Kirupa",
"lastName": "Chinnathambi",
"special": {
"admin": true,
"userID": 203
},
"devices": [
{
"type": "laptop",
"model": "Macbook Pro"
},
{
"type": "phone",
"model": "iPhone XS"
}
]
};
To read the value stored by firstName, you can do either of the following:
exampleJSON.firstName
exampleJSON["firstName"]
Both lines will return a value of Kirupa. There is no right or wrong answer to whether you want to use the dot notation approach or the array approach to access the value you are interested in. Use whatever you are comfortable with, but my personal preference is to use dot notation. Passing in property names as strings makes me queasy, so I will only highlight the dot notation approach in the code snippets that you will be seeing.
Similar to what you saw earlier, to access the value stored by lastName, you can do this:
exampleJSON.lastName
For simple properties that store simple values, life is pretty simple. The only very VERY minor complication you'll run into is when working with more complex values made up of Objects and Arrays. To read a value stored inside an Object, just keep dotting into each property until you reach the property that stores the value you are interested in.
Here is what trying to access the value stored by the userID property will look like:
exampleJSON.special.userID
Arrays are no different, but you will eventually have to switch into array notation once you get to the property that stores your array values. If we wanted to access the model value of the first device in the devices array, we can type something that looks as follows:
exampleJSON.devices[0].model
Because the devices property refers to an array, you can also perform stereotypical array-like operations such as the following:
let devicesArray = exampleJSON.devices;
for (let i = 0; i < devicesArray.length; i++) {
let type = devicesArray[i].type;
let model = devicesArray[i].model;
// do something interesting with this data!
}
To reiterate what you saw in the previous section, your JSON values can be either strings, numbers, objects, arrays, booleans, or nulls. Everything that JavaScript supports for a given data type that you encounter inside your JSON object, you can easily take advantage of.
In our example, we had our JSON data defined neatly inside the exampleJSON variable. There is no doubt in anybody's mind that what we're dealing with is a real JS object that uses JSON semantics.
With real-world scenarios, that won't always be the case. Your JSON data could be coming from a variety of different sources, and not all of them will return the JSON data into this workable format that we saw. Many will return JSON data as raw text. You will have something that looks like a JSON object, but you can't interact with the data like you would when you are working with a real JSON object.
To deal with this, you have the JSON.parse method that takes your "fake" JSON data as its argument:
function processRequest(e) {
if (xhr.readyState == 4 && xhr.status == 200) {
let response = JSON.parse(xhr.responseText);
selectInitialState(response.region);
}
}
As you can see from our highlighted line, this method takes whatever JSON-looking data that you end up with and converts it into a real JSON object that you can work with more easily. Whenever I am working with JSON data from an external source, I always use JSON.parse just to be safe.
We just had a section devoted entirely to reading values from JSON data. It would seem logical to also have a section that is focused on writing JSON data. As it turns out, writing JSON data just isn't all that popular unless you are saving JSON data to a file or doing something with web services. If you are doing either of these tasks, statistically you are doing development on Node or writing code in a programming language other than JavaScript.
For front-end development, I can't think of too many cases where information on writing JSON would be useful. If you run into the rare situation where you need to do something other than reading JSON data, my recommendation is for you to use Google!
At one point in time, this article would have been focused on XML. Even today, XML is still widely popular as a file format for storing or communicating information. Only in a world where the web browser is king (aka the world that we live in) is where JSON is extremely popular. That doesn't mean that JSON doesn't exist in other situations. App configuration for both web as well as non-web situations are increasingly using JSON as their way of representing data. Who knew?!!
Just a final word before we wrap up. If you have a question and/or want to be part of a friendly, collaborative community of over 220k other developers like yourself, post on the forums for a quick response!
:: Copyright KIRUPA 2024 //--