Open any live cricket score app during an IPL match. Every few seconds, without you touching anything, the number on your screen changes — "RCB 187/4 (18.2)" becomes "RCB 191/4 (18.4)" a moment later. Your phone did not "watch" the match. It does not have eyes. Somewhere, a computer at the stadium is recording every ball, and your phone is asking that computer, again and again, "what is the score right now?" — and getting an answer back, fast enough that it feels live. This chapter is about exactly how that question and that answer are actually built: as an API request and a JSON response. By the end, you will be able to read raw JSON the way you read a table, write your own JSON by hand, and trace through code that pulls a specific number out of a nested JSON structure.
The problem: two programs need to agree on a "shape"
Suppose the stadium's computer answered your phone's question in plain English: "India are at one hundred eighty seven runs for the loss of four wickets, in eighteen point two overs, and the not-out batter is Kohli." A human reading that sentence understands it instantly. But the score app on your phone is not a human — it is a program, and a program cannot "understand English." It needs to find the runs value, isolate it as a number, and place it into a specific spot on the screen. Extracting "187" out of a free-flowing English sentence, reliably, every single time, for every possible sentence structure the stadium computer might use, is a genuinely hard problem. If the sentence next time were phrased "With four down, India have reached 187," a program built to expect the first sentence pattern would break.
The fix computer scientists settled on decades ago is simple in spirit: stop sending free-form sentences between programs. Instead, agree in advance on a strict, predictable shape for the data — a shape so rigid that a program can pull out "the value next to the word runs" without any guessing. That agreed-upon shape, for the vast majority of the modern internet, is called JSON — JavaScript Object Notation. Despite the name, JSON is not "JavaScript code" that runs — it is a plain text format for representing data, and it is understood by Python, Java, C++, Swift, and effectively every programming language in use today. The "JavaScript" in the name is historical: the format's syntax was borrowed from how JavaScript writes objects and arrays in source code, but JSON itself is just text sitting in a file or flowing across the internet, waiting to be read by any language.
JSON, built up from one value
Start with the smallest possible piece of information: one player's live score. In JSON, that single record is written as a set of key–value pairs wrapped in curly braces:
{
"name": "Virat Kohli",
"runs": 82,
"balls": 61,
"out": false
}
Read this literally, piece by piece, because every symbol here is a rule, not a style choice:
- The outermost
{ }marks this as a JSON object — a labelled bundle of data, similar in spirit to a Python dictionary or a single row of a spreadsheet where each column has a name. - Each line is a key (the label, always written in double quotes —
"name","runs") followed by a colon, followed by a value. - Values can be different types:
"Virat Kohli"is a string (text, in double quotes),82and61are numbers (no quotes — quoting a number turns it into a string, which is a common bug), andfalseis a boolean (true or false, also unquoted). JSON has a fifth value type worth knowing now:null, which means "this field exists, but there is deliberately no value" — for instance,"playerOfMatch": nullwhile the match is still in progress. - A comma separates each key–value pair from the next. The last pair in the object has no trailing comma — writing one is a syntax error in JSON, even though it is often tolerated in JavaScript source code. This is the single most common mistake beginners make when hand-writing JSON.
Now, a scoreboard is never just one player — it is a whole batting line-up. To represent "a list of things," JSON uses square brackets [ ] for an array, with each item separated by commas:
[
{ "name": "Rohit Sharma", "runs": 45, "balls": 32, "out": true },
{ "name": "Virat Kohli", "runs": 82, "balls": 61, "out": false }
]
Notice what just happened: an array's items do not have to be plain numbers or strings — here, each item in the array is itself a full object. This is the core trick that makes JSON powerful: objects can contain arrays, and arrays can contain objects, nested as deep as the data actually requires. A full scorecard nests this one level further — a top-level object describing the match, holding an array of batters:
{
"team": "Royal Challengers Bengaluru",
"totalRuns": 187,
"wickets": 4,
"overs": 18.2,
"batters": [
{ "name": "Rohit Sharma", "runs": 45, "out": true },
{ "name": "Virat Kohli", "runs": 82, "out": false }
]
}
Read this out loud in terms of shape, not content: "an object with four simple fields, plus one field called batters whose value is an array of two objects." Once you can narrate the shape of a JSON block like that, you can navigate any JSON you are handed, no matter how large.
Where the JSON comes from: the "API" half of the story
JSON is just the format of the answer. The API (Application Programming Interface) is the agreed system for asking the question in the first place. When your score app wants fresh data, it sends an HTTP request to a specific web address called an endpoint — something shaped like https://api.example.com/matches/1184/score — using the GET method, which simply means "give me data, don't change anything." The server at that address does its work (checks its database, calculates the current total) and sends back a response, which has two important parts: a numeric status code telling the app whether the request succeeded (200 means OK, 404 means "that endpoint or match ID doesn't exist," 500 means the server itself broke), and a body — which, for almost every modern API, is JSON text exactly like the scorecard above.
It is worth being precise about one thing students often blur: what actually travels over the internet is a single long string of characters — {"team":"Royal... and so on — not a "JavaScript object" or a "Python dictionary." JSON in transit is just text. Only after your app receives that text does it run a parsing step that converts the text into a real, usable data structure in whatever language the app is written in. This distinction — JSON-the-text versus JSON-after-parsing — matters because a lot of real bugs come from forgetting that a freshly received API response is still just one giant string until you deliberately parse it.
Worked example: parsing a response in Python
Here is that exact scorecard, arriving as one JSON string, being parsed and read using Python's built-in json module. Trace every line and its exact output:
import json
response_text = '''
{
"team": "Royal Challengers Bengaluru",
"totalRuns": 187,
"wickets": 4,
"overs": 18.2,
"batters": [
{ "name": "Rohit Sharma", "runs": 45, "out": true },
{ "name": "Virat Kohli", "runs": 82, "out": false }
]
}
'''
data = json.loads(response_text)
print(type(data)) # <class 'dict'>
print(data["team"]) # Royal Challengers Bengaluru
print(data["totalRuns"]) # 187
print(type(data["batters"])) # <class 'list'>
print(data["batters"][1]["name"]) # Virat Kohli
print(data["batters"][1]["runs"]) # 82
Walk through why each output is what it is. json.loads ("load string") reads the text and converts JSON objects into Python dictionaries and JSON arrays into Python lists — that conversion is why type(data) reports dict: the outer { } became a dictionary. data["team"] looks up the value stored under the key "team", exactly like looking up a word in that dictionary's index. data["batters"] is a list of two dictionaries, because JSON's [ ] became a Python list — so to reach one specific batter, you index into the list first with [1] (the second item, since indexing starts at 0, so index 0 is Rohit Sharma and index 1 is Kohli), and only then look up a key inside that item with ["name"]. Chained access like data["batters"][1]["name"] should be read right to left in your head as "go to the list called batters, take item 1 from it, then take the name field from that item" — mirroring exactly how you narrated the JSON's shape earlier.
Now a slightly harder, very realistic task: total the runs of every batter using a loop, rather than typing each index by hand.
total_from_batters = 0
for batter in data["batters"]:
total_from_batters = total_from_batters + batter["runs"]
print(total_from_batters) # 127
Trace it rather than trusting the comment: the loop variable batter takes the value {"name": "Rohit Sharma", "runs": 45, "out": True} on the first pass, so batter["runs"] is 45, and total_from_batters becomes 0 + 45 = 45. On the second pass, batter becomes Kohli's dictionary, batter["runs"] is 82, and the running total becomes 45 + 82 = 127. This habit — re-adding the numbers yourself instead of trusting a comment or an answer key — is exactly what you should do with every code trace in this chapter, and with any JSON-parsing code you write on your own.
A misconception worth correcting directly
A very common belief among beginners is: "JSON objects are basically the same as JavaScript objects, so if it works as JavaScript, it's valid JSON." This is false in a way that causes real errors. JavaScript object literals are far more relaxed than JSON: JavaScript allows unquoted keys ({name: "Kohli"}), single quotes, trailing commas, and even comments. Valid JSON requires none of that leniency — keys must always be in double quotes, string values must always be in double quotes (never single), and a trailing comma anywhere is an outright syntax error that will make json.loads (or any JSON parser, in any language) raise an exception and refuse to read the entire block, not just the broken part. Compare these two, which look almost identical:
Not valid JSON: Valid JSON:
{ {
name: 'Kohli', "name": "Kohli",
runs: 82, "runs": 82
} }
The left version would run fine as JavaScript source code but is rejected by every JSON parser. When an API call fails with a parsing error, checking for exactly these differences — missing quotes, single quotes, a stray trailing comma — is usually the fastest way to find the bug.
Reading a real-shaped example: weather data
Cricket scores are one shape of API. Weather apps use a different but structurally similar one — this is the value of understanding JSON's shape rather than memorizing any one API: once you understand nesting, every JSON API becomes readable on sight. A typical weather API response, in the kind of shape real weather services use, looks like this:
{
"city": "Bengaluru",
"current": {
"temperatureC": 24,
"condition": "Cloudy",
"humidity": 68
},
"forecast": [
{ "day": "Tuesday", "highC": 27, "lowC": 19, "rain": true },
{ "day": "Wednesday", "highC": 29, "lowC": 20, "rain": false },
{ "day": "Thursday", "highC": 28, "lowC": 20, "rain": false }
]
}
Notice this introduces one more shape you have not yet named: "current" is itself a nested object (not an array), because "current conditions" is a single fixed set of facts, while "forecast" is an array because it is a repeating list of similar day-records. This is the actual design skill behind JSON: use an object when a field is a fixed one-of-a-kind bundle of facts, and use an array when a field is a repeating collection of similar items. Given this JSON, the path to Thursday's high temperature is data["forecast"][2]["highC"] — index 2, because Tuesday is index 0, Wednesday is index 1, and Thursday is index 2.
Real APIs also frequently omit fields that don't apply, rather than including them with a blank value, so production code typically uses .get() instead of [ ] to avoid crashing when a key is missing:
humidity = data["current"].get("humidity", "not available")
uv_index = data["current"].get("uvIndex", "not available")
print(humidity) # 68
print(uv_index) # not available
.get(key, default) looks up key and returns default instead of crashing if that key simply is not present in this particular response — "uvIndex" was never included in the JSON above, so Python prints the fallback string rather than raising an error. Using plain data["current"]["uvIndex"] on this same JSON would immediately crash the program with a KeyError, which is precisely the kind of real-world bug that comes from assuming every API response always contains every field.
How the request and response actually travel
The diagram below shows the complete round trip your score app makes, tying the API half (the request/response over HTTP) to the JSON half (the text format of what comes back) into one picture.
Two arrows, one box of raw text, one final box: that is the whole system underneath every "live" number on every app on your phone. Step 1 is the API request. Step 2 is the API response, and its body is JSON. Step 3 is the parsing step from the Python example — turning that JSON text into a dictionary the app's own code can use to update what you see. The reason this matters at Grade 8 level and not just as trivia: this exact three-step pattern is how IRCTC shows live PNR status, how a UPI app shows a transaction as "successful," and how a weather widget updates — different data, same three steps, same JSON rules underneath.
Practice
- This JSON was rejected by a parser. Find the exact syntax error and state the fix:
{"player": "Bumrah", "wickets": 3,} - Write valid JSON for a Class 8 student's report card with three fields:
"name"(string),"rollNumber"(number), and"marks"— an array of three objects, each with"subject"and"score". - Using the weather JSON from this chapter, write the exact chained expression (like
data["forecast"][2]["highC"]) that would give you Wednesday's"rain"value, and state what it evaluates to. - Given the batters array
[{"name": "Rohit Sharma", "runs": 45, "out": true}, {"name": "Virat Kohli", "runs": 82, "out": false}], write a short loop (in words or code) that counts how many batters are out, and state the final count. - A teammate says: "An API is the same thing as JSON." Explain, in two sentences, why that statement mixes up two different things.
Summary
An API is the agreed system by which one program asks another program for data or an action, over the internet, using an endpoint URL, a method like GET, and a status code that reports success or failure. JSON is the text format almost all modern APIs use to shape that data: objects { } hold labelled key–value pairs for a fixed bundle of facts, arrays [ ] hold ordered lists of similar items, and the two nest inside each other to represent data of any real-world complexity, from a single player's score to a full match scorecard. Every JSON key and string value must use double quotes, no comma may follow the last item in an object or array, and JSON arriving over the network is plain text until a parsing step (such as Python's json.loads) converts it into a dictionary or list your program can actually work with. Reading nested JSON is a matter of narrating its shape out loud — object or array, one level at a time — and chaining lookups ([ ] for both dictionary keys and list indices) exactly in that order.
Think About It
Think about this: How would you explain json apis to a friend who has never seen a computer? What real-world analogy would you use? Imagine you had to build a system using these concepts — what would be your first step? Try this: before moving on, write down three things you learned and one question you still have.