JSON Square Brackets [ ] Explained

14 min readJSON & Data

Introduction

JSON has exactly two ways to group things, and the entire format hinges on telling them apart. Square brackets [ ] wrap an array — an ordered list of values. Curly braces { } wrap an object — a set of key/value pairs. Almost every “why won’t my JSON parse” question I see traces back to confusing those two, or to a small slip inside the brackets like a stray comma.

This guide focuses on the square bracket. We will cover what an array actually is, when to reach for [ ] instead of { }, the two patterns you will write most often (arrays of objects and nested arrays), and a long, practical section on the bracket mistakes that produce cryptic parser messages. Everything here is plain JSON you can paste into a validator and watch behave exactly as described.

Tip: Paste any snippet from this article into the JSON Formatter or JSON Validator to see the structure indented and to catch an unclosed bracket the instant it happens.

Square brackets [ ] mean an array

An array is an ordered sequence of values separated by commas. The order is part of the data — the first item is always the first item. Each value can be any JSON type: a string, a number, a boolean, null, an object, or another array.

// The simplest array: three strings
["red", "green", "blue"]

// Arrays can mix any JSON value type
[42, "hello", true, null, { "ok": 1 }, [1, 2]]

// An empty array is perfectly valid
[]

Notice there are no keys. You do not write names for the positions; you reach a value by its index instead. In application code that looks like colors[0] returning "red". That single difference — positional access with no keys — is the whole reason arrays exist alongside objects.

Brackets vs braces: when to use which

The choice is not stylistic. It encodes what the data is. Use an array when you have a collection of similar things whose order may matter and which you would loop over. Use an object when you have one thing described by named attributes.

AspectSquare brackets [ ] — arrayCurly braces { } — object
HoldsA list of valuesNamed key/value pairs
OrderOrdered and meaningfulNo guaranteed order
Access byPosition / indexKey name
Keys present?NoYes, must be strings
Typical useMany similar items you loop overOne entity with attributes

The same information can often be modelled either way, and seeing the contrast side by side makes the rule concrete. Here are three usernames as an array versus as an object:

// As an array — a plain ordered list
["ada", "linus", "grace"]

// As an object — only makes sense if each name labels something
{
  "ada":   "admin",
  "linus": "editor",
  "grace": "viewer"
}

The array says “here are three users.” The object says “here are three users, each with a role.” If you only have the names and no per-name attribute, forcing an object would mean inventing meaningless keys — a classic sign you wanted an array all along.

Arrays of objects: the shape of almost every API response

The single most common real-world structure is an array whose elements are objects: [{...}, {...}]. A list endpoint that returns “all users” or “all products” nearly always returns this. The outer [ ] is the collection; each inner { } is one record.

{
  "users": [
    { "id": 1, "name": "Ada",   "active": true },
    { "id": 2, "name": "Linus", "active": false },
    { "id": 3, "name": "Grace", "active": true }
  ]
}

Read it inside out: users is a key whose value is an array; that array holds three objects; each object has the same three keys. The objects do not have to be identical, but in a well-designed collection they share a shape so consumers can iterate without special-casing each element. The comma placement is the part that trips people up: every object inside the array is separated from the next by a comma, and the last object has no trailing comma after its closing brace.

Nested arrays: arrays inside arrays

Because an array element can itself be an array, you can build grids and trees. A two-dimensional array — a matrix — is just an array of arrays:

// A 3×3 matrix: an array containing three arrays
[
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
]

// Mixed nesting: an array of objects, each holding an array
[
  { "name": "Ada",   "tags": ["admin", "core"] },
  { "name": "Grace", "tags": ["viewer"] }
]

The trick to reading nested structures is to count brackets from the outside in and let an indented formatter do the matching for you. Each [ must eventually meet a matching ] at the same depth, and the same for braces. When a deeply nested payload looks like an unreadable wall of punctuation, that is exactly the moment to format it rather than to squint at it.

Bracket mistakes that cause “unexpected token”

This is where most searches for square brackets actually start: something broke. Below are the five bracket-related errors I see most, each with the wrong version, the message a parser typically throws, and the fix. The exact wording varies between JSON.parse, Python’s json, and Go, but the cause is the same.

1. Trailing comma after the last element

[1, 2, 3, ]   ❌   →   Unexpected token ] in JSON
[1, 2, 3]     ✅

JSON does not allow a comma before a closing bracket, even though JavaScript array literals do. This is the number one cause of hand-edited JSON failing, because the syntax is legal in the language people write JSON in.

2. Missing comma between elements

[1 2 3]       ❌   →   Unexpected number / expected ','
[1, 2, 3]     ✅

The parser reads the first value fine, then finds another value where it expected either a comma or the closing bracket. Common when copy-pasting lines together and dropping the separator.

3. Using [ ] where you meant { }

["name": "Ada"]          ❌   →   Unexpected token :
{ "name": "Ada" }        ✅

A colon means “key: value,” which only belongs in an object. The moment a parser sees a : inside square brackets it errors, because arrays have no keys. If you want named fields, you wanted braces.

4. Mismatched or unclosed brackets

[{ "a": 1 ]              ❌   →   Unexpected token ] / expected '}'
[{ "a": 1 }]             ✅

Here an object was opened with { but closed with ]. Each opener needs its matching closer of the same kind. Unclosed brackets often report the error at the end of the document (“unexpected end of input”), which is misleading — the real problem is higher up.

5. Single quotes or unquoted strings (often paired with bracket bugs)

['a', 'b']               ❌   →   Unexpected token '
["a", "b"]               ✅

JSON strings must use double quotes. This is not a bracket error, but it shows up constantly in the same hand-written arrays, so it is worth fixing in the same pass.

Empty array [ ] versus null

These look interchangeable and are not. An empty array [] says “there is a list here and it currently has zero items.” null says “there is no list at all.” The distinction matters most in API design and is a place I have watched bugs hide for weeks.

{ "items": [] }      // user has an empty cart — safe to .map() over
{ "items": null }    // no cart object — .map() throws at runtime

My rule on the producing side: if a field is conceptually always a collection, return [] when it is empty, never null. Consumers can then iterate unconditionally and never write a null check. Returning null for “no results” forces every caller to guard against it, and one caller will inevitably forget. Reserve null for “this value genuinely does not exist” — not for an empty list.

Yes, a JSON document can start with [

A surprising number of developers believe a JSON file must begin with {. Since the JSON spec was standardized, the top-level value can be any JSON value — including an array. A file that is nothing but [1, 2, 3] is completely valid.

That said, here is a hard-won bit of advice: for a public API, prefer wrapping a top-level array inside an object, like { "data": [ ... ] }. A bare top-level array gives you nowhere to add pagination, metadata, or a future field without a breaking change — you would have to alter the very top of the response shape. The wrapper costs three characters now and saves a major version bump later. (There was also a historical security concern with returning a bare top-level JSON array from a browser endpoint; modern defenses make it far less relevant, but the forward-compatibility argument alone is enough.)

How to find a bracket error fast

When a payload refuses to parse and the message is unhelpful, stop reading it character by character. Three faster moves:

  • Format it. An indented view makes an unclosed or mismatched bracket jump out, because the indentation stops lining up at the exact point of the error. Run it through the JSON Formatter.
  • Validate it. A JSON Validator reports the line and column of the first failure, which is usually one trailing comma or one wrong closer.
  • Let an editor match brackets. Place the cursor on a [ and your editor will highlight its partner. If it has none, you found the bug.

If the JSON is broken in several places at once — common with hand-edited config — the JSON Repair tool can fix trailing commas and quote issues in one pass so you can see the real structure underneath.

Frequently asked questions

Can a JSON file start with [?

Yes. The top-level value can be an array, object, string, number, boolean, or null. A file containing only [1, 2, 3] is valid JSON. For public APIs an object wrapper is still recommended for future flexibility.

What is the difference between [ ] and { } in JSON?

Square brackets create an ordered array of values accessed by position. Curly braces create an object of named key/value pairs accessed by key. Arrays have no keys; objects always do.

Why does my JSON array say “unexpected token”?

Almost always a trailing comma before ], a missing comma between elements, a colon inside an array, or a mismatched bracket. Format and validate the snippet to get the exact line.

Can a JSON array hold different types?

Yes — [1, "two", true, null] is valid. But mixing types makes the array awkward to consume, so most real arrays are homogeneous (all of one shape). Mix types only when the structure genuinely calls for it.

Are square brackets required for a single value?

No. A single value like 42 or "hello" is valid JSON on its own. Use brackets only when you intend a list — [42] is a one-element array, which is different from the bare value 42.

Is [] the same as null?

No. [] is an existing but empty list you can safely iterate; null is the absence of a value and will throw if you try to loop over it.

Related tools on ByteJSON

Z

Written by Zhisan

Independent Developer · Last updated June 2026