Skip to content
100% in your browser. Nothing you paste is uploaded — all processing runs locally. Read more →

What is JSON?

On this page
  1. The six value types
  2. A complete example
  3. Where JSON came from
  4. Why it won
  5. What JSON is NOT
  6. The gotchas every developer hits
    1. 1. Numbers don’t distinguish int from float
    2. 2. Strings are always double-quoted
    3. 3. No trailing commas
    4. 4. No NaN, Infinity, or undefined
    5. 5. Dates are strings
    6. 6. UTF-8, but the spec says UTF-16
    7. 7. Maps with integer keys
  7. JSON tooling at the command line
  8. In your language
  9. When JSON is the wrong tool
  10. Try the tools
  11. Related across the network

JSON — JavaScript Object Notation — is a text-based data interchange format. It’s how nearly every API on the web sends structured data: a server returns JSON, your browser parses it, your app renders it. The format is simple, human-readable, and supported in every programming language.

This page is the practical introduction. For just formatting/validating JSON, jump straight to the formatter or validator.

The six value types

A JSON value is exactly one of these:

TypeExamples
Object{"name": "Alice", "age": 42}
Array[1, 2, 3]
String"hello" (always double quotes)
Number42, 3.14, -1.5e10
Booleantrue or false
Nullnull

That’s it. There are no dates, no integers-vs-floats distinction, no bytes type, no comments. The simplicity is the point — a JSON parser fits in a few hundred lines of code in any language.

A complete example

{
  "user": {
    "id": "0e6f1b8c-2c33-4f1f-9c0b-2a3d4e5f6a7b",
    "email": "alice@example.com",
    "verified": true,
    "createdAt": "2026-04-26T12:00:00Z",
    "preferences": {
      "theme": "dark",
      "newsletter": false
    },
    "tags": ["admin", "early-access"]
  }
}

This shows nearly everything: nested objects, an array, all primitive types, and the convention for representing dates as ISO 8601 strings (since JSON has no date type).

Where JSON came from

Doug Crockford specified JSON in the early 2000s as a subset of JavaScript syntax suitable for data interchange. The format quickly outgrew JavaScript — by 2010 it was the de facto standard for REST APIs, replacing XML in most web services.

The official specification is now RFC 8259 (December 2017), with the looser ECMA-404 standard covering the syntax. Both define the same format with minor differences in what “valid” means.

Why it won

What JSON is NOT

The gotchas every developer hits

1. Numbers don’t distinguish int from float

JSON has one numeric type: a 64-bit IEEE-754 double. Practical consequence: integers larger than 2⁵³ lose precision.

{ "id": 9007199254740993 }

This parses as 9007199254740992 in JavaScript — the trailing 3 becomes 2. Workarounds: send large IDs as strings (most APIs do), or use a parser that supports BigInt on the receiving side.

2. Strings are always double-quoted

{ 'name': 'Alice' }       // ❌ INVALID — single quotes
{ name: "Alice" }         // ❌ INVALID — unquoted key
{ "name": "Alice" }       // ✅

JavaScript’s looser object syntax accepts the first two; JSON does not.

3. No trailing commas

{ "a": 1, "b": 2, }       // ❌ INVALID
[1, 2, 3,]                // ❌ INVALID

JSON5 and JSONC allow them; strict JSON does not.

4. No NaN, Infinity, or undefined

{ "x": NaN }              // ❌ INVALID
{ "x": Infinity }         // ❌ INVALID
{ "x": undefined }        // ❌ INVALID — undefined is a JS-only value

If you have these in your data, encode as null or as a sentinel string.

5. Dates are strings

JSON has no date type. The conventional encoding is ISO 8601:

{ "createdAt": "2026-04-26T12:00:00Z" }

Every language’s standard library can parse this. Other formats (Unix epoch milliseconds as a number, RFC 2822 strings) work too — pick one and document it.

6. UTF-8, but the spec says UTF-16

Technically JSON is “Unicode text” and can be UTF-8, UTF-16, or UTF-32. In practice, everyone uses UTF-8 and parsers expect it. Set your Content-Type to application/json; charset=utf-8 and don’t worry about it.

7. Maps with integer keys

JSON objects only have string keys. If you want a map keyed by integers, you have to stringify them:

{ "1": "Alice", "2": "Bob" }    // keys are strings, not numbers

This trips up languages where the runtime distinguishes the two (Python, Go’s map[int]string, etc.).

JSON tooling at the command line

# pretty-print
echo '{"a":1}' | jq .

# validate (exit 0 if valid)
echo "$INPUT" | jq empty

# extract a field
curl https://api.example.com/users/42 | jq '.email'

# filter an array
echo '[{"x":1},{"x":2}]' | jq '.[] | select(.x > 1)'

jq is the universal JSON Swiss Army knife at the shell. jp, gron, and fx are alternatives worth knowing.

In your language

// JavaScript / TypeScript — built-in
const obj = JSON.parse(text);
const text = JSON.stringify(obj, null, 2);
# Python — built-in
import json
obj = json.loads(text)
text = json.dumps(obj, indent=2)
// Go — encoding/json in stdlib
var v map[string]any
json.Unmarshal([]byte(text), &v)
out, _ := json.MarshalIndent(v, "", "  ")
// Rust — serde_json crate
let v: serde_json::Value = serde_json::from_str(text)?;
let text = serde_json::to_string_pretty(&v)?;

When JSON is the wrong tool

For everything else — REST APIs, web app state, log aggregation, simple config — JSON is the boring correct answer.

Try the tools