JSON (JavaScript Object Notation) is a lightweight text format for storing and exchanging structured data. Despite the name, JSON has nothing to do with JavaScript at runtime — it's a universal format understood by virtually every programming language, database, and API on the planet.
If you've ever worked with a REST API, a config file, or a web application, you've encountered JSON.
JSON in 30 seconds
A JSON document is plain text made up of key-value pairs, arrays, and nested objects:
{
"name": "Ana Kovač",
"age": 28,
"active": true,
"scores": [95, 87, 100],
"address": {
"city": "Podgorica",
"country": "Montenegro"
},
"nickname": null
}
That's it. No tags, no schema required. Open in any text editor, inspect in any browser DevTools, pass between any two systems.
JSON data types
JSON supports exactly six data types:
| Type | Example | Notes |
|---|---|---|
| String | "hello world" |
Always double quotes, never single |
| Number | 42, 3.14, -7, 1e10 |
No separate int/float distinction |
| Boolean | true, false |
Lowercase only |
| Null | null |
Lowercase only |
| Object | {"key": "value"} |
Unordered set of key-value pairs |
| Array | [1, 2, 3] |
Ordered list of any values |
What JSON does NOT support: undefined, Date, Function, BigInt, binary data, comments, trailing commas. These are the most common sources of JSON parse errors.
JSON syntax rules
Five rules that catch 90% of JSON errors:
- Keys must be strings — wrapped in double quotes:
{"name": "Ana"}, not{name: "Ana"}. - Strings use double quotes —
"value", never'value'or backticks. - No trailing commas —
{"a": 1, "b": 2}is valid;{"a": 1, "b": 2,}is not. - No comments —
// commentand/* comment */are illegal in JSON. - Numbers have no leading zeros —
07is invalid;7is fine.
Use a JSON formatter and validator to catch these instantly.
JSON vs XML — a quick comparison
Both formats represent structured data, but JSON has largely replaced XML for web APIs:
| JSON | XML | |
|---|---|---|
| Verbosity | Compact | Verbose (opening + closing tags) |
| Readability | Easy for humans | Harder to scan |
| Comments | Not allowed | Allowed |
| Attributes | No concept | Supports attributes |
| Data types | 6 built-in | All strings by default |
| Schema | Optional (JSON Schema) | Optional (XSD, DTD) |
| Best for | APIs, configs, web | Documents, SOAP, RSS |
Rule of thumb: use JSON for APIs and application data; use XML when the document structure matters (RSS feeds, Office files, SOAP services).
Reading and writing JSON
JavaScript
JSON is native to JavaScript via JSON.parse() and JSON.stringify():
// Parse JSON string → object
const text = '{"name":"Ana","age":28}';
const obj = JSON.parse(text);
console.log(obj.name); // "Ana"
// Stringify object → JSON string
const data = { name: "Ana", age: 28, active: true };
const json = JSON.stringify(data, null, 2); // pretty-print with 2-space indent
console.log(json);
// {
// "name": "Ana",
// "age": 28,
// "active": true
// }
// Gotcha: undefined and functions are stripped
JSON.stringify({ a: 1, b: undefined, c: () => {} });
// → '{"a":1}'
// Gotcha: Date objects become strings
JSON.stringify({ created: new Date() });
// → '{"created":"2026-07-13T10:00:00.000Z"}'
Python
Python's json module is in the standard library:
import json
# Parse JSON string → dict
text = '{"name": "Ana", "age": 28}'
obj = json.loads(text)
print(obj["name"]) # "Ana"
# Read from file
with open("data.json", "r", encoding="utf-8") as f:
data = json.load(f)
# Serialize dict → JSON string
data = {"name": "Ana", "age": 28, "active": True}
text = json.dumps(data, indent=2, ensure_ascii=False)
# Write to file
with open("out.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
# Gotcha: Python True/False → JSON true/false automatically
# Gotcha: ensure_ascii=False keeps non-ASCII chars (e.g. "Kovač") intact
Go
Go uses encoding/json from the standard library. Struct tags control the field names:
package main
import (
"encoding/json"
"fmt"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Active bool `json:"active"`
}
func main() {
// Parse JSON bytes → struct
raw := []byte(`{"name":"Ana","age":28,"active":true}`)
var p Person
if err := json.Unmarshal(raw, &p); err != nil {
panic(err)
}
fmt.Println(p.Name) // "Ana"
// Serialize struct → JSON bytes
out, err := json.MarshalIndent(p, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(out))
}
// Gotcha: unexported (lowercase) struct fields are ignored
// Gotcha: omitempty tag omits zero-value fields:
// Score int `json:"score,omitempty"` — omitted if score == 0
PHP
PHP parses JSON to associative arrays or objects:
<?php
// Parse JSON string → associative array
$text = '{"name":"Ana","age":28}';
$data = json_decode($text, associative: true);
echo $data['name']; // "Ana"
// Parse as object
$obj = json_decode($text);
echo $obj->name; // "Ana"
// Serialize array → JSON string
$data = ['name' => 'Ana', 'age' => 28, 'active' => true];
$json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
// Always check for errors
if (json_last_error() !== JSON_ERROR_NONE) {
throw new RuntimeException('JSON error: ' . json_last_error_msg());
}
// Read from file
$data = json_decode(file_get_contents('data.json'), true);
Common JSON structures
Single object — one record:
{ "id": 1, "name": "Ana", "email": "ana@example.com" }
Array of objects — a collection (most common API response):
[
{ "id": 1, "name": "Ana" },
{ "id": 2, "name": "Marko" }
]
Wrapped response — API envelope with metadata:
{
"data": [{ "id": 1 }, { "id": 2 }],
"total": 2,
"page": 1,
"per_page": 20
}
Nested config — hierarchical settings:
{
"database": {
"host": "localhost",
"port": 5432,
"name": "myapp"
},
"cache": {
"driver": "redis",
"ttl": 3600
}
}
6 common JSON pitfalls
| Pitfall | Problem | Fix |
|---|---|---|
| Single quotes | {'key': 'val'} is invalid JSON |
Always double quotes |
| Trailing comma | [1, 2, 3,] breaks parsers |
Remove trailing commas |
| Comments | // this breaks parsers |
Use JSONC or strip before parsing |
| Date as Date object | JavaScript Date isn't JSON |
Use ISO 8601 strings: "2026-07-13T10:00:00Z" |
| BigInt | Numbers > 2⁵³ lose precision in JS | Use strings for large IDs |
| Circular references | Object A → B → A can't be serialised | Break the cycle before stringify |
JSON Schema — optional typing
JSON Schema lets you define the shape of a JSON document and validate data against it:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["name", "age"],
"properties": {
"name": { "type": "string", "minLength": 1 },
"age": { "type": "integer", "minimum": 0, "maximum": 150 },
"email": { "type": "string", "format": "email" }
},
"additionalProperties": false
}
Libraries like ajv (JS), jsonschema (Python), and santhosh-tekuri/jsonschema (Go) validate data against a schema at runtime — useful for API request validation.
FAQ
Is JSON the same as a JavaScript object?
No. A JavaScript object is an in-memory data structure; JSON is a text serialisation format. They look similar, but JS objects can have functions, undefined, and symbol keys — none of which exist in JSON.
Can JSON have comments? No. The JSON spec forbids comments. If you need comments in a config file, use TOML, YAML, or JSONC (a superset supported by VS Code and some tools).
What's the difference between JSON.parse and JSON.stringify?
JSON.parse converts a JSON string into a native data structure. JSON.stringify does the reverse — converts a native object into a JSON string.
Why does my JSON look like one long line?
It's minified (all whitespace removed). Use a JSON formatter or JSON.stringify(data, null, 2) to pretty-print it.
Can JSON store binary data (images, files)? Not directly. Encode binary as a Base64 string first, then store that string in JSON. Alternatively, send binary as multipart form data and JSON metadata separately.
What's NDJSON (Newline-Delimited JSON)? NDJSON is a format where each line is a valid JSON object. It's popular for log files and streaming APIs because you can process one line at a time without loading the entire document into memory.