Concepts / Constructing JSON with Python Dictionaries and Lists

Constructing JSON with Python Dictionaries and Lists

json.loads() transforms a JSON string into a Python data structure by parsing the text and building corresponding lists, dictionaries, and primitive values.

  • Programming
Interactive lab

Try it: Parsing JSON into Python

How json.loads() reads JSON text token by token and builds Python dicts, lists, strings, numbers, True/False and None, how an access path like data["users"][0]["name"] walks that structure, and what json.dumps() writes back.

How it works

  1. The scanner reads the next token: a brace or bracket, a string in double quotes, a number, true / false / null, or a ',' / ':' delimiter.
  2. '{' starts a Python dict and '[' a list; both are pushed on a parse stack until their closing '}' or ']'.
  3. Inside a dict every key must be a double-quoted string followed by ':' and a value; items are separated by ','.
  4. Anything else stops the parse with JSONDecodeError, reporting the message, line, column and character position.
  5. The access path is applied one subscript at a time: dicts take keys (KeyError if missing), lists take integer indexes (IndexError if out of range).
  6. json.dumps() turns the Python objects back into JSON text (True → true, None → null), optionally indented.

Default run (43 steps): json.loads() receives 105 characters of text. The scanner starts at char 0 and reads one token at a time. … json.dumps(data, indent=2) turns the Python objects back into JSON text (171 characters): True → true, None → null, and strings get double quotes.

Simplified: Written from scratch to match CPython 3.12's json module (messages and positions checked against it); input is limited to 400 characters and 24 nesting levels, and the access path accepts only ["key"] and [index] subscripts. Python 3.13 reports a trailing comma in an object with a different message.

Educational simulation

Loading the simulation…

From Text to Structure

A JSON document often arrives as text, but your Python program needs a usable data structure. The function json.loads() parses a JSON string and returns a new Python object built from the structure represented in that text. The original string is unchanged, so assign the returned object to a variable before trying to access its contents.

JSON string{"users": [...]}json.loads()parse textPython data structurelists, dictionaries,primitive valuesinputreturns
What happens to JSON text when json.loads() parses it?

The Container Relationship

The shape of the JSON determines the shape of the returned Python data. A JSON object becomes a Python dictionary, and a JSON array becomes a Python list. Nested objects and arrays remain nested after parsing. Primitive values remain values inside those containers. This means the brackets and braces in the original text provide a map for understanding the Python structure that json.loads() creates.

JSON objectcurly bracesJSON arraysquare bracketsPython dictionarykey-value fieldsPython listordered elementsbecomesbecomes
How does each JSON object or array correspond to a Python container?

A User List Step by Step

Code walkthrough
import json

data = '[{"id": 1, "x": 10, "name": "Ari"}, {"id": 2, "x": 20, "name": "Bea"}]'
info = json.loads(data)

print(len(info))
print(info[0]['name'])
print(info[1]['x'])
  1. 1
    The outer square brackets in data indicate a list.
  2. 2
    The two brace-delimited sections inside the list indicate two dictionary-like JSON objects.
  3. 3
    After parsing, info is a list containing two dictionaries.
  4. 4
    info[0] selects the first dictionary, and ['name'] selects its name field.
  5. 5
    info[1] selects the second dictionary, and ['x'] selects its x field.
  • data is a JSON string.
  • json.loads(data) returns the parsed Python structure and assigns it to info.
  • The outer square brackets represent a list, so len(info) counts two elements.
  • Each list element is a dictionary, so info[0]['name'] uses a list index followed by a dictionary key.
  • The second dictionary's x field is accessed with info[1]['x'].
Output
2
Ari
20
infolistindex 0first dictionarynameAriindex 1second dictionaryx20[0]['name'][1]['x']
How do dictionary keys and list indexes guide the path from the parsed object to a nested value?

Reading the Nested Shape

Accessing parsed JSON is a structure-tracing task. At every level, first determine what kind of container you are holding. If the current value is a list, use an index such as [0] or [1]. If it is a dictionary, use a key such as ['name'] or ['x']. In the user example, the path info[0]['name'] means: start with the top-level list, select its first element, then select the name field from the resulting dictionary.

infolistindex 0dictionaryid1x10nameAri[0]['id']['x']['name']
How can you determine whether each level is a dictionary or list before choosing a key or index?

Tracing a Deeper Path

python
Output
viewer

The access path crosses several levels. parsed is a dictionary, so ['users'] selects its users field. That field contains a list, so [0] selects the first user dictionary. The user dictionary contains a roles field, so ['roles'] selects another list. Finally, [1] selects the second element of that list. The correct access expression follows the actual container type at each step.

Knowing the Expected Shape

  1. 1
    Check the input before parsing: confirm that the value passed to json.loads() is a string containing JSON text.
  2. 2
    Read the outermost symbols: square brackets indicate a list structure, while curly braces indicate a dictionary structure.
  3. 3
    Map each nested level: record whether the next access requires a list index or a dictionary key.
  4. 4
    Use keys and indices that actually exist in the parsed structure.
  5. 5
    If access fails, inspect the structure layer by layer instead of guessing at a longer access expression.
Code walkthrough
import json

data = '{"users": [{"name": "Ari"}]}'
parsed = json.loads(data)

print(parsed)
print(parsed['users'])
print(parsed['users'][0])
print(parsed['users'][0]['name'])
  1. 1
    Start with the complete parsed object so you can compare the actual structure with your expectation.
  2. 2
    Print one access step at a time.
  3. 3
    When a step succeeds, use the revealed value to choose the next key or index.
  4. 4
    If a step fails, the failing level identifies where your expectation and the actual structure differ.
  • The first print reveals the complete parsed structure.
  • The second print reveals the value stored under the users key.
  • The third print reveals the dictionary selected at list index 0.
  • The final print reveals the value stored under the name key.
Output
{'users': [{'name': 'Ari'}]}
[{'name': 'Ari'}]
{'name': 'Ari'}
Ari

Mistakes During Parsing

  • Common mistake

    Forgetting to import json before calling json.loads().

    What it looks like
    data = '{"name": "Ari"}'
    parsed = json.loads(data)
    Why it fails

    The name json has not been made available to the program.

    Do this instead

    Import the json module before using json.loads().

  • Common mistake

    Passing a non-string object to json.loads().

    What it looks like
    parsed = json.loads({'name': 'Ari'})
    Why it fails

    json.loads() is used to parse a JSON string, not an already-created Python object.

    Do this instead

    Verify that the input is a string containing JSON text before calling json.loads().

  • Common mistake

    Using a dictionary key where the current value is a list.

    What it looks like
    parsed['users']['name']
    Why it fails

    If users contains a list, the next step must select a list element before selecting a field.

    Do this instead

    Follow the structure one level at a time, such as parsed['users'][0]['name'] when that path matches the actual data.

  • Common mistake

    Using a list index where the current value is a dictionary.

    What it looks like
    parsed[0]
    Why it fails

    A dictionary is accessed through keys, not list positions.

    Do this instead

    Use the appropriate dictionary key, such as parsed['users'], when the top-level value is a dictionary.

  • Common mistake

    Accessing a field that does not exist.

    What it looks like
    parsed['username']
    Why it fails

    The requested key may not be present in the parsed dictionary.

    Do this instead

    Compare the requested key with the documented structure and inspect the parsed value to confirm its available fields.

Practice the Access Path

EASY

Given this code, identify the type of container at each step and predict the value printed by the final line:

import json

data = '{"groups": [{"members": ["Ari", "Bea"]}]}'
parsed = json.loads(data)
print(parsed['groups'][0]['members'][1])
Hints
  • Start by identifying the top-level container.
  • After selecting groups, determine whether the next step needs a key or an index.
  • The final index selects the second element of the members list.

What do you think happens?

What will the final print statement output?

  • Ari

  • Bea

  • The complete groups dictionary

  • An error because groups is a dictionary

Reveal answer
Answer:

Bea

parsed is a dictionary, groups contains a list, index 0 selects the first group dictionary, members contains a list, and index 1 selects its second element.

Key Takeaways

  1. 1
    json.loads() parses a JSON string and returns a new Python data structure; the original string remains unchanged.
  2. 2
    JSON objects correspond to Python dictionaries, and JSON arrays correspond to Python lists in the parsed structure.
  3. 3
    Use dictionary keys for dictionary levels and list indexes for list levels.
  4. 4
    Reliable access requires knowing the expected structure, which is why API documentation matters.
  5. 5
    When debugging, check the input, identify the parsed structure, and trace each access step separately.

At a glance

  • json.loads() transforms JSON text into a new Python object.
  • The JSON shape guides the Python shape: objects become dictionaries and arrays become lists.
  • Nested access combines dictionary keys and list indexes according to the structure at each level.
  • You need advance knowledge of the expected data structure to navigate parsed JSON effectively.
  • Layer-by-layer inspection is a practical way to diagnose parsing and access errors.

Related concepts

More concepts starting with C