Skip to main content

What Are the Differences Between Python Dictionary and JSON

Python dictionaries and JSON look nearly identical at first glance, both using curly braces and key-value pairs. This visual similarity causes frequent confusion, but they serve fundamentally different purposes. A dictionary is a data structure that lives in your program's memory. JSON is a text format designed for exchanging data between systems. Understanding the distinction is essential when working with APIs, configuration files, and data storage.

This guide explains the key differences, shows how to convert between the two formats, and covers common pitfalls that trip up developers.

Python Dictionary: An In-Memory Data Structure

A dictionary is a native Python object stored in RAM. It maps keys to values, supports various hashable types as keys, and can hold references to any Python object, including functions, classes, and custom instances:

from datetime import datetime

# Dictionaries support diverse key and value types
data = {
"name": "Alice",
1: "integer key", # Non-string keys are valid
(2, 3): "tuple key", # Any hashable type works
"active": True, # Python boolean (capital T)
"data": None # Python None (capital N)
}

print(type(data))
print(data[1])
print(data[(2, 3)])

Output:

<class 'dict'>
integer key
tuple key

Dictionaries can also store complex Python objects that have no equivalent in other languages:

from datetime import datetime

user = {
"name": "Bob",
"created": datetime.now(), # datetime object
"process": lambda x: x * 2, # function reference
"scores": {10, 20, 30} # set
}

print(type(user["created"]))
print(user["process"](5))

Output:

<class 'datetime.datetime'>
10

JSON: A Text Serialization Format

JSON (JavaScript Object Notation) is a string designed for data interchange between systems, languages, and platforms. It follows strict syntax rules that differ from Python in several important ways:

import json

# JSON is always a string
json_string = '{"name": "Alice", "age": 30, "active": true}'

print(type(json_string))

# Parse it into a Python dictionary
parsed = json.loads(json_string)
print(type(parsed))

Output:

<class 'str'>
<class 'dict'>

JSON has specific formatting requirements:

  • Keys must be strings enclosed in double quotes
  • String values must use double quotes (single quotes are invalid)
  • Booleans are lowercase: true and false
  • Null values use the keyword null
  • No trailing commas are allowed
warning

Single quotes are the most common source of JSON parsing errors. Python accepts both quote styles for strings, but JSON strictly requires double quotes:

import json

# Wrong: single quotes are not valid JSON
bad_json = "{'name': 'Alice'}"
try:
json.loads(bad_json)
except json.JSONDecodeError as e:
print(f"Error: {e}")

# Correct: double quotes only
good_json = '{"name": "Alice"}'
result = json.loads(good_json)
print(result)

Output:

Error: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
{'name': 'Alice'}

Converting Between Dictionaries and JSON

The built-in json module provides two primary functions for conversion:

  • json.dumps(): Converts a Python dictionary to a JSON string (serialization)
  • json.loads(): Converts a JSON string to a Python dictionary (deserialization)
import json

# Dictionary to JSON string
user_dict = {"name": "Alice", "age": 30, "active": True, "data": None}
json_string = json.dumps(user_dict)
print(f"JSON string: {json_string}")
print(f"Type: {type(json_string)}")

print()

# JSON string back to dictionary
parsed_dict = json.loads(json_string)
print(f"Dictionary: {parsed_dict}")
print(f"Type: {type(parsed_dict)}")

Output:

JSON string: {"name": "Alice", "age": 30, "active": true, "data": null}
Type: <class 'str'>

Dictionary: {'name': 'Alice', 'age': 30, 'active': True, 'data': None}
Type: <class 'dict'>

Notice how Python's True becomes JSON's true, and Python's None becomes JSON's null. These conversions happen automatically in both directions.

Handling Non-Serializable Types

JSON only supports a small set of basic types. If your dictionary contains Python-specific objects like datetime, set, or custom classes, json.dumps() will raise a TypeError. You need to provide a custom encoder to handle these types:

import json
from datetime import datetime

data = {
"event": "login",
"timestamp": datetime.now()
}

# This fails because datetime is not JSON serializable
try:
json.dumps(data)
except TypeError as e:
print(f"Error: {e}")

# Solution: provide a custom encoder function
def json_encoder(obj):
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError(f"Object of type {type(obj)} is not JSON serializable")

result = json.dumps(data, default=json_encoder)
print(result)

Output:

Error: Object of type datetime is not JSON serializable
{"event": "login", "timestamp": "2026-02-18T21:38:10.125495"}

Key Pitfall: Integer Keys Become Strings

JSON only supports string keys. When you serialize a dictionary with non-string keys, they are automatically converted to strings. This means a round-trip conversion does not preserve the original key types:

import json

original = {1: "one", 2: "two", 3: "three"}
print(f"Original keys: {list(original.keys())}")
print(f"Key types: {[type(k) for k in original.keys()]}")

# Round-trip through JSON
json_string = json.dumps(original)
restored = json.loads(json_string)

print(f"\nRestored keys: {list(restored.keys())}")
print(f"Key types: {[type(k) for k in restored.keys()]}")

# This lookup now fails
try:
print(restored[1])
except KeyError:
print("\nKeyError: integer key 1 no longer exists")
print(f"Must use string key: {restored['1']}")

Output:

Original keys: [1, 2, 3]
Key types: [<class 'int'>, <class 'int'>, <class 'int'>]

Restored keys: ['1', '2', '3']
Key types: [<class 'str'>, <class 'str'>, <class 'str'>]

KeyError: integer key 1 no longer exists
Must use string key: one
tip

If your code relies on non-string dictionary keys, be aware that serializing to JSON and back will silently change them to strings. This is a common source of bugs in applications that store data as JSON and then try to look up values using the original key types.

Type Mapping Reference

Python TypeJSON TypeNotes
dictobjectKeys are converted to strings
list, tuplearrayTuples become arrays (lists on round-trip)
strstringMust use double quotes in JSON
int, floatnumberJSON makes no distinction between int and float
TruetrueLowercase in JSON
FalsefalseLowercase in JSON
NonenullDifferent keyword

Feature Comparison

FeatureDictionaryJSON
What it isIn-memory Python objectText string for data exchange
Key typesAny hashable typeStrings only
Value typesAny Python objectStrings, numbers, booleans, null, arrays, objects
Quote styleSingle or doubleDouble quotes only
Trailing commasAllowedInvalid
Boolean formatTrue / Falsetrue / false
Null formatNonenull
Primary purposeProgram logic and data manipulationData interchange between systems

Summary

A Python dictionary is an in-memory object that you manipulate directly in your code. JSON is a text string that you send over networks, store in files, or use to exchange data between different systems and programming languages.

  • You cannot "parse" a dictionary because it is already a live Python object.
  • You parse JSON strings into dictionaries using json.loads(), and convert dictionaries into JSON strings using json.dumps().

When converting between the two, be aware of the automatic type transformations:

  • True becomes true
  • None becomes null
  • integer keys become string keys
  • tuples become arrays

Understanding these differences prevents confusion and subtle bugs when working with APIs, configuration files, and data storage.