JSON Object Syntax: Names, Quoted Strings, and Double Quotes (RFC 8259)
Dev Tools

JSON Object Syntax: Names, Quoted Strings, and Double Quotes (RFC 8259)

Introduction: JSON Objects Look Simple, but the Rules Are Precise

A JSON object is the workhorse of nearly every modern web API, configuration file, and data interchange format. It looks trivial: a pair of curly braces with some keys and values inside. Yet a surprising share of "invalid JSON" errors come from a handful of small rule violations — an unquoted key, a single quote where a double quote belongs, a trailing comma, or a stray comment. These are not stylistic preferences. They are hard requirements defined by the specification that governs JSON, and any conforming parser will reject text that breaks them.

This guide is a precise, example-driven reference for how JSON objects must be written according to RFC 8259 — the current Internet Standard for the JSON data interchange format. We will cover what an object actually is, why names must be strings, why strings must use double quotes, the six structural characters, the prohibition on trailing commas and comments, and the surprisingly subtle question of duplicate names. Every rule is paired with valid and invalid examples so you can see exactly where parsers draw the line. As you work through them, paste your own snippets into our JSON formatter and validator to confirm each rule in practice — it flags the exact character where a document stops being valid JSON.

What RFC 8259 Actually Is

RFC 8259, "The JavaScript Object Notation (JSON) Data Interchange Format," was published in December 2017. It is designated STD 90, meaning it is a full Internet Standard rather than a mere proposal, and it obsoletes the earlier RFC 7159 and RFC 4627. It exists alongside ECMA-404, the standard maintained by Ecma International; the two documents describe the same grammar and are intentionally kept in agreement, so a document that is valid under one is valid under the other.

The RFC defines JSON's four primitive types (strings, numbers, booleans, and null) and two structured types (objects and arrays). It deliberately keeps the grammar small. There is no versioning, no schema mechanism, and no provision for comments or extensions inside the syntax itself. That minimalism is why JSON travels so well between languages: there is very little to disagree about. Our focus here is the object type, which is where most syntax mistakes occur.

An Object Is an Unordered Set of Name/Value Pairs

RFC 8259 defines a JSON object as an unordered collection of zero or more name/value pairs, where a name is a string and a value is any valid JSON value. The pairs are wrapped in curly braces, each name is separated from its value by a colon, and pairs are separated from one another by commas.

The smallest possible object is the empty object, written as two adjacent braces:

{}

A populated object looks like this:

{
"id": 42,
"name": "Ada Lovelace",
"active": true
}

Two consequences of the definition are worth internalizing. First, order is not significant. The specification describes an object as unordered, so a parser is not required to preserve the sequence in which pairs appeared, and two objects with the same pairs in a different order represent the same data. In practice many parsers (including JavaScript's) do preserve insertion order for string keys, but you must never rely on ordering for correctness — a conforming implementation is free to reorder. Second, an object may contain zero pairs; the empty object is perfectly valid and common as a default value or placeholder.

Values inside an object can be any JSON value, including nested objects and arrays. This composition is what makes JSON expressive:

{
"user": {
"name": "Grace",
"roles": ["admin", "editor"]
},
"count": 0
}

Names (Keys) Must Be Strings

This is the rule most often violated by developers coming from JavaScript. In JavaScript source code you can write an object literal with bare identifier keys — { name: "Grace" } — and the language accepts it. JSON does not. In JSON, every name in a name/value pair must be a string, which means it must be enclosed in double quotes.

Valid — the name is a quoted string:

{ "name": "Grace" }

Invalid — the name is a bare identifier, not a string:

{ name: "Grace" }

Invalid — the name uses single quotes, which do not produce a JSON string:

{ 'name': "Grace" }

Because names are strings, they can contain any characters a JSON string can contain, including spaces, punctuation, and Unicode: { "full name": "Grace Hopper", "emoji": "ok" } is valid. A name can even be the empty string: { "": "value" } is legal, though rarely a good idea. Numbers, booleans, and null are not valid names; { 42: "x" } is invalid because 42 is a number token, not a string. If you need a numeric key, quote it: { "42": "x" }.

Strings Must Be Wrapped in Double Quotes (U+0022)

A JSON string — whether it is being used as a name or as a value — must begin and end with a double quotation mark, the character " at Unicode code point U+0022. No other delimiter is permitted. Single quotes (', U+0027), backticks, and the various "curly" typographic quotation marks are not string delimiters in JSON. This single rule eliminates a whole family of syntax errors once you internalize it.

Valid:

{ "message": "hello world" }

Invalid — single quotes around the value:

{ "message": 'hello world' }

Invalid — curly typographic quotes, which often sneak in when text is copied from a word processor:

{ "message": "hello world" }

Certain characters inside a string must be escaped with a backslash. A literal double quote inside the string is written as \", and a backslash is written as \\. Control characters — code points from U+0000 through U+001F — must not appear literally in a string; they are written using escape sequences instead. The common named escapes are \n (line feed), \t (tab), \r (carriage return), \b (backspace), \f (form feed), and \/ (an optional escape for the forward slash). Any Unicode character can also be written with a \u escape followed by four hexadecimal digits, for example é for the letter e with an acute accent.

Here a value legitimately contains a quotation mark and a newline, both escaped:

{ "quote": "She said \"hello\"", "line": "first\nsecond" }

Writing an actual, unescaped newline or tab inside the quotes would make the document invalid. This is why editors sometimes report an "unexpected token" partway through a long string — an unescaped control character broke it.

JSON Object Syntax: Names, Quoted Strings, and Double Quotes (RFC 8259)

The Six Structural Characters

RFC 8259 identifies exactly six structural characters that form the skeleton of any JSON document. Everything else is a value, a name, or insignificant whitespace. The six are:

  • { — begin-object (left curly brace)
  • } — end-object (right curly brace)
  • [ — begin-array (left square bracket)
  • ] — end-array (right square bracket)
  • : — name-separator (colon), between a name and its value
  • , — value-separator (comma), between pairs or array elements

The specification permits insignificant whitespace before or after any of these structural characters. The allowed whitespace characters are the space, horizontal tab, line feed, and carriage return. This is why pretty-printed JSON with indentation and line breaks is exactly as valid as minified JSON on a single line — the whitespace between tokens carries no meaning. Whitespace is not permitted inside a token, however: you cannot put a space in the middle of the keyword true or between the digits of a number.

No Trailing Commas, No Comments

Two of JSON's most famous omissions trip up newcomers constantly, and both are deliberate.

Trailing commas are not allowed. The comma is a separator between pairs, so there must be nothing after the final pair before the closing brace. A comma with no pair following it is a syntax error.

Valid:

{
"a": 1,
"b": 2
}

Invalid — the comma after 2 has no pair following it:

{
"a": 1,
"b": 2,
}

The same rule applies to arrays: [1, 2, 3,] is invalid. Many programming languages tolerate trailing commas in their own literals, which is exactly why the mistake is so easy to carry into JSON.

Comments are not allowed. There is no // line comment or /* ... */ block comment in JSON. The grammar has no production for them, so any parser that strictly follows RFC 8259 will reject a document containing one. If you need to annotate a JSON document, the common workaround is to add a dedicated string field such as { "_comment": "explanation here", "value": 1 }. Formats that layer comments on top of JSON — like JSON5 or JSONC — are separate, non-standard dialects; they are not JSON as defined by the RFC, and a strict validator will flag their comments.

Duplicate Names: Allowed by the Grammar, but Behavior Is Unspecified

This is one of the most misunderstood corners of the standard. RFC 8259 does not forbid an object from having two pairs with the same name. A document like this is syntactically valid JSON:

{ "id": 1, "id": 2 }

However, the RFC notes that names within an object should be unique, and it explicitly states that the behavior of software receiving an object with duplicate names is unpredictable. Some parsers keep the last occurrence, some keep the first, some collect all values, and some raise an error. Because the outcome is implementation-dependent, you must treat duplicate names as a bug even though the grammar tolerates them. Never rely on any particular resolution of a duplicate key — different systems in the same pipeline may resolve it differently, silently corrupting data. When you generate JSON, guarantee unique names; when you consume it, consider rejecting objects with duplicates outright. Our JSON formatter makes duplicates easy to spot while you inspect a payload.

Worked Examples: Valid vs Invalid at a Glance

Putting the rules together, here is a fully valid object that exercises nested structures, escaped characters, and every primitive type:

{
"id": 1001,
"name": "Order \"A\"",
"paid": false,
"discount": null,
"items": [
{ "sku": "X1", "qty": 2 },
{ "sku": "Y7", "qty": 1 }
],
"note": "line one\nline two"
}

And here is a catalogue of the most common ways an object goes wrong, each a single-line reason:

  • { id: 1 } — name is not a quoted string.
  • { "id": 1, } — trailing comma before the closing brace.
  • { "id": 1 // primary key
    }
    — comments are not permitted.
  • { "id": '1' } — value uses single quotes instead of double quotes.
  • { "id": 1 "name": "x" } — missing comma between pairs.
  • { "id" 1 } — missing colon between name and value.
  • { "id": 1 }} — unbalanced braces.

How These Rules Fit into Real-World JSON Work

Understanding object syntax at this level pays off directly when you build and debug APIs. Malformed request bodies, subtly broken config files, and payloads that a strict server rejects almost always trace back to one of the rules above. For a broader tour of conventions that go beyond raw syntax — response envelopes, naming, and error formats — see our companion guide on JSON best practices for API development. And if you are choosing a format for human-edited configuration where comments and trailing commas matter, our comparison of YAML vs JSON explains when JSON's strictness is an asset and when a friendlier format serves you better.

When you need a schema to enforce structure beyond syntax — required names, value types, and allowed properties — validate documents against a contract with our JSON tooling. Syntax validity is only the first gate; a document can be perfectly valid JSON and still be wrong for your application, which is where schema validation takes over.

Validate Every Rule with the JSON Formatter

Our JSON formatter and validator is the fastest way to confirm everything in this guide. Paste a document and it pretty-prints valid JSON, pinpoints the exact character where invalid JSON fails, and highlights structural issues like unbalanced braces, missing commas, and unquoted names. Because it runs entirely in your browser, no data ever leaves your machine — safe for pasting production payloads and credentials. Try the invalid examples above one by one: each will fail at precisely the character the rule predicts, turning these abstract requirements into something you can see and remember.

← Back to Blog