Working with JSON: A Developer's Guide
JSON is the lingua franca of web APIs and configuration files. It's small enough to learn in an hour but has enough edge cases to trip up working developers for years.
Published April 28, 2026JSON (JavaScript Object Notation) is a text-based format for representing structured data. Despite the name, it's language-independent — every major programming language has libraries for parsing and generating it. Its six data types are: strings, numbers, booleans, null, arrays, and objects (key-value maps).
The JSON specification in short
{
"name": "Alice",
"age": 30,
"active": true,
"scores": [98, 87, 92],
"address": {
"city": "Portland",
"zip": "97201"
},
"nickname": null
}
Rules that catch people out:
- Keys must be double-quoted strings. Single quotes are not valid JSON.
- No trailing commas. A comma after the last item in an array or object is a parse error.
- No comments. JSON has no comment syntax (unlike JavaScript, YAML, or TOML).
- Numbers must be valid JSON numbers: no leading zeros (
007is invalid), no hex (0xff), no Infinity, no NaN.
Parsing and serializing
# Python
import json
# Parse JSON string into a Python dict
data = json.loads('{"name": "Alice", "age": 30}')
print(data["name"]) # Alice
# Serialize Python dict to JSON string
text = json.dumps({"name": "Bob", "scores": [10, 20]}, indent=2)
print(text)
# Read from file / write to file
with open("data.json") as f:
config = json.load(f)
with open("output.json", "w") as f:
json.dump(config, f, indent=2)
// JavaScript
const data = JSON.parse('{"name": "Alice", "age": 30}');
console.log(data.name); // Alice
const text = JSON.stringify({ name: "Bob", scores: [10, 20] }, null, 2);
console.log(text);
Common pitfalls
Large integers lose precision in JavaScript. JSON numbers are IEEE 754 doubles. Integers beyond 2^53 (9,007,199,254,740,992) cannot be represented exactly. This is a real problem when APIs return 64-bit database IDs as JSON numbers. The fix is to send them as strings:
// Unsafe: ID may be rounded
{ "user_id": 9876543210987654321 }
// Safe: ID as string
{ "user_id": "9876543210987654321" }
undefined is not null in JavaScript. JSON has null but no undefined. When you serialize a JavaScript object, properties with undefined values are silently dropped. This can cause subtle data loss:
JSON.stringify({ a: 1, b: undefined, c: null })
// Result: '{"a":1,"c":null}' — b is gone entirely
Date objects need special handling. JSON has no date type. JSON.stringify(new Date()) produces an ISO 8601 string like "2026-04-28T10:00:00.000Z", which is a convention, not part of the spec. Parsing it back gives a string, not a Date object — you must convert explicitly.
Circular references cannot be serialized. If an object references itself (directly or via a chain), JSON.stringify throws a TypeError. Use a library like flatted or restructure your data to avoid cycles.
Querying JSON with jq
jq is a command-line JSON processor, invaluable for inspecting API responses:
# Pretty-print a JSON file
jq . data.json
# Extract a field
jq '.name' data.json
# Extract from an array
jq '.[0].email' users.json
# Filter an array
jq '.[] | select(.active == true)' users.json
# Get all keys
jq 'keys' data.json
JSON Schema for validation
JSON Schema is a vocabulary for describing and validating JSON. It lets you define the expected structure of a JSON document and validate incoming data before processing 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 }
},
"additionalProperties": false
}
Libraries exist for every major language to validate a JSON document against a schema. Validating at the boundary of your system (when data comes in from an API or user input) catches problems early rather than letting malformed data propagate into your database.
JSON is simple by design. That simplicity is why it won: it's easy to parse, easy to generate, and easy to read. Its constraints (no comments, no dates, no integers beyond double precision) are trade-offs the designers made deliberately. Understanding those trade-offs lets you work around them cleanly rather than being surprised by them.