Python JSON

Tutorial 28 of 65 · pythondeck.com Python course

The json module serialises Python objects to JSON text and vice versa. Top-level dicts, lists, strings, numbers, booleans and None are supported. Use dumps/loads for strings, dump/load for files.

JSON is the lingua franca of web APIs and config files. Python's json module maps JSON objects, arrays, strings, numbers, booleans, and null to dict, list, str, int/float, bool, and None. It does not natively serialise datetime, sets, or custom classes—you extend encoding explicitly.

Text JSON must use UTF-8 on the wire; json.dumps produces ASCII with \u escapes by default unless ensure_ascii=False. Large payloads benefit from streaming or alternative formats (MessagePack, etc.) when appropriate.

json.dumps / json.loads for strings; dump / load for file objects.

The indent parameter for readable output; separators for compact production payloads.

Custom types via default on JSONEncoder or a default callable in dumps.

Decoding hooks: object_hook for dicts, parse_float / parse_int for precision.

JSON Schema validation is external (e.g. jsonschema) but important at API boundaries.

Security: never use eval on JSON; parse with json.loads only.

JSON numbers map to Python int or float; very large integers may lose precision if parsed as float. Use parse_int or decode as string when handling 64-bit IDs from JavaScript.

Duplicate keys in JSON objects are invalid per spec but some parsers last-wins; do not rely on duplicates. Pretty-printed config files should still be validated after edits.

For untrusted input, cap size and depth before parsing to mitigate denial-of-service. Combine parsing with schema validation before using data in SQL or shell commands.

Serialising datetime or Decimal without a custom default handler.

Assuming JSON allows comments or trailing commas (it does not).

Using float for currency amounts that need exact decimal representation.

Calling eval on data that should be parsed as JSON.

Forgetting encoding="utf-8" when writing JSON files on Windows.

Define a stable schema and validate with jsonschema or pydantic models.

Implement default for non-JSON-native types; document the wire format (e.g. ISO dates).

Use ensure_ascii=False only when the consumer expects UTF-8 end-to-end.

Load from binary files opened in text mode with explicit UTF-8 encoding.

Re-read the examples below with these ideas in mind; change variable names and inputs to match your own project.

The program below demonstrates dumps/loads. Read the comments on each line, run the code, then change names or values to see how the output shifts.

# Example: Dumps/loads
# Run in the REPL or save as a .py file and execute with python.
import json
data = {"name": "Ada", "skills": ["py", "math"]}
s = json.dumps(data, indent=2)
print(s)
print(json.loads(s))

This sample walks through file round-trip in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.

# Example: File round-trip
# Run in the REPL or save as a .py file and execute with python.
import json
with open("out.json", "w") as f:
    json.dump({"ok": True}, f)
with open("out.json") as f:
    print(json.load(f))

Here is a hands-on illustration of custom encoder. Follow the inline comments first; only then execute the snippet and compare the result with what you expected.

# Example: Custom encoder
# Run in the REPL or save as a .py file and execute with python.
import json
from datetime import datetime
class DTEnc(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, datetime):
            return o.isoformat()
        return super().default(o)

print(json.dumps({"t": datetime.now()}, cls=DTEnc))

The program below demonstrates dump load. Read the comments on each line, run the code, then change names or values to see how the output shifts.

# json converts Python objects to text and back
import json  # standard JSON codec
data = {"name": "Ada", "scores": [99, 100], "active": True}  # object graph
text = json.dumps(data, indent=2)  # pretty string with newlines
print(text)  # human-readable JSON
back = json.loads(text)  # parse string into Python types
print(back["name"], back["scores"][0])  # Ada 99
print(type(back["scores"]))  # list, not JSON array type
with open("sample.json", "w", encoding="utf-8") as f:  # write file
    json.dump(data, f)  # stream encode to file object

This sample walks through custom encoder in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.

# default=str handles non-JSON-native objects like datetime
from datetime import datetime, timezone  # non-serializable by default
import json  # json module
event = {"at": datetime.now(timezone.utc), "ok": True}  # mixed dict
print(json.dumps(event, default=str))  # stringify unknown types
class SetEncoder(json.JSONEncoder):  # subclass hook
    def default(self, obj):  # called for unsupported types
        if isinstance(obj, set):  # detect sets
            return sorted(obj)  # convert to JSON-friendly list
        return super().default(obj)  # fall back to base error
payload = {"tags": {"a", "b"}}  # set value
print(json.dumps(payload, cls=SetEncoder))  # encoded list

« Python Math All tutorials Python RegEx »