JSON Syntax and Data Model
Goals
After this lesson, you can distinguish “text that looks like JSON” from valid JSON; identify the six value types, object members, and array elements; and explain why a top-level scalar, permitted whitespace, escaping, and the difference between an absent value, null, and an empty value all matter.
First, distinguish three layers
Beginners often mix up these three things:
python_value = {"enabled": True, "fallback": None}
json_text = '{"enabled": true, "fallback": null}'
json_string_value = '"{\\"enabled\\": true}"'python_valueis a Pythondictin memory.json_textis a Python string whose contents happen to be one JSON text.- After parsing,
json_string_valueis still a string whose contents merely look like an object. This is usually an accidental second serialization.
An interface transmits bytes. A parser decodes the bytes into text, then converts the text into language-level objects. Schema validation and business logic operate on the parsed value, not on the braces themselves.
One JSON text represents one value
The core form in RFC 8259 can be read as: permitted whitespace + one value + permitted whitespace. A top-level value need not be an object or array; all of these are valid standalone JSON texts:
{"name":"agent"}["search", "read"]42nullSome APIs additionally require the top-level value to be an object. That is an interface contract, not a general JSON syntax rule. Parse the data first, then explicitly check the top-level type.
The six value types and their Python mappings
{
"name": "meeting-assistant",
"enabled": true,
"max_steps": 8,
"temperature": 0.2,
"tools": ["search_notes", "read_calendar"],
"fallback": null,
"limits": {
"timeout_seconds": 30
}
}| JSON type | Example | Default Python result | Key boundary |
|---|---|---|---|
| object | {"a": 1} | dict | Member names must be strings; object meaning does not depend on order. |
| array | [1, "x", null] | list | Elements are ordered and may be heterogeneous. |
| string | "agent" | str | Uses double quotes; control characters must be escaped. |
| number | 8, 0.2, 1e3 | int, float | JSON does not declare bit width, Decimal, or date types. |
| boolean | true, false | True, False | JSON literals are lowercase. |
| null | null | None | Represents an explicit empty value; the contract defines its business meaning. |
An object member is written as "name": value, with commas between members; array elements are also separated by commas. A trailing comma is not allowed after the last item.
Permitted whitespace is very limited
JSON grammar recognizes only four characters as whitespace outside structures: space, tab, LF, and CR. A full-width space, arbitrary invisible Unicode whitespace, or a special character copied from elsewhere may not be valid. When debugging, inspect the parser’s line and column and the source bytes; do not hide a data problem by deleting every invisible character.
The most common invalid forms
None of these lines is standard JSON:
{'name': 'agent'} # single quotes
{name: "agent"} # key is not double-quoted
{"enabled": True} # Python Boolean
{"fallback": None} # Python null
{"items": [1, 2,]} # trailing comma
{"value": undefined} # JSON has no undefined
{"id": 001} # meaningless leading zero in an integer
{"score": NaN} # RFC 8259 disallows non-finite numbers
{"hex": 0x10} # hexadecimal numbers are unsupported
{"a": 1} {"b": 2} # two values without framingThe # text after each example is teaching commentary, not part of the value being judged. Standard JSON does not support comments. Extended formats such as JSON5 may allow some of these forms, but never silently send extension syntax to a strict JSON API.
Strings, escaping, and Windows paths
Double quotes, backslashes, and U+0000–U+001F control characters inside strings must be escaped:
{
"quote": "They said: \\"stop the task.\\"",
"path": "D:\\\\data\\\\input.json",
"two_lines": "first\nsecond",
"tab": "left\tright",
"text": "Unicode text can be written directly as UTF-8"
}Do not confuse JSON escaping with Python source-string escaping. When you handwrite the same text in Python source, a backslash may first be interpreted by the Python string parser. A safer approach is to construct a Python object and let json.dumps encode it.
Absent fields, null, empty strings, and empty containers
{}{"deadline": null}{"deadline": ""}{"reviewers": []}They can respectively mean:
- an absent field: it was not supplied, an old value remains, or a default applies;
null: explicitly clear the value, or its value is unknown;- an empty string: a string was supplied, but it contains no characters;
- an empty array: a collection was supplied, and it currently contains no elements.
A parser preserves only the data shape; it cannot know whether “clear” or “retain” is the business intent. The contract must say so for every field.
Same text, same value, and same business meaning
These texts have different bytes, but their parsed objects can represent the same name/value mapping:
{"a":1,"b":2}{
"b": 2,
"a": 1
}Object-member order should not be business semantics across systems; array order does have semantics. The string "1" and the number 1 are not equal, and null is not the same as an absent field. For signatures, hashes, or cache keys, do not assume arbitrary serialized text is stable; canonicalization comes later.
Common errors and troubleshooting
- Copying a Python
repras JSON: generate it withjson.dumps, then validate it with a parser. - Hand-concatenating JSON: quotes, backslashes, and control characters easily break boundaries; construct an object and serialize it.
- Editing a Schema when you see
JSONDecodeError: syntax parsing occurs before Schema validation, so fix the text first. - Assuming all JSON is an object: a top-level scalar is valid, though an application may explicitly reject it.
- Writing comments into a production payload: use a separate documentation field or a configuration format that explicitly supports comments.
Exercises
- Convert the Python literal
{'ok': True, 'value': None}into valid JSON. - Write valid JSON strings for the path
D:\agent\config.jsonand for a sentence containing double quotes. - Decide whether
42,[true],{"x": 1,}, and{"x": +1}are valid, and explain why. - Define the three meanings of absent,
null, and empty-stringdisplay_namein a PATCH request. - Explain why reordering object fields normally should not change business behavior, while reordering array elements can.
Self-test
- Can a JSON object key be an unquoted number?
- Is top-level
falsea valid JSON text? - Does JSON natively support dates, comments, and
undefined? - Why must a Windows path in a JSON string use doubled backslashes?
- Must different text represent different parsed values?
Summary and next step
JSON is syntax for “one serialized value,” not a permission system, database, or business model. The next lesson hands text to Python and examines compatibility-oriented defaults in the standard library: Python Parsing, Serialization, and Strict Mode. Return to the JSON Learning Index.
References
Source review date: 2026-07-14.