๐Ÿ“ Python

JSON: Persisting Data Like a Real Game ๐Ÿ’พ

0
Author
04e5cc8b-58ac-4bdc-bdee-661bbb
๐Ÿ“…
Published
03.04.2026
โฑ๏ธ
Reading time
8 min
๐Ÿ‘๏ธ
Views
125
๐ŸŒฑ
Level
Beginner

Goal: Learn to save and load data in JSON format.


๐Ÿค” Why Save Data at All?

Imagine: you built a game, the player played for 2 hours, scored 1000 points… and closed the program. They open it again โ€” everything is reset! ๐Ÿ˜ฑ

Problem: Variables in Python only live as long as the program is running.

Solution: Save data to a file so it persists!


๐Ÿ“ฆ What Is JSON?

JSON (JavaScript Object Notation) is a text file format for storing data.

It looks almost like a Python dictionary:

{
  "name": "Alice",
  "age": 25,
  "balance": 1000.50,
  "transactions": ["deposit", "withdraw", "deposit"]
}

Why JSON is so popular:
- โœ… Human-readable (not binary)
- โœ… Supported by every programming language
- โœ… Used by websites, APIs, and databases
- โœ… Built-in support in Python!


๐Ÿ”„ Python โ‡” JSON โ€” Type Mapping

Python JSON
dict Object {}
list Array []
str String "text"
int, float Number 42, 3.14
True, False true, false
None null

Example:

# Python data
data = {
    "name": "Ivan",
    "scores": [10, 20, 30],
    "is_active": True,
    "balance": None
}

# In the JSON file it will look like:
# {
#   "name": "Ivan",
#   "scores": [10, 20, 30],
#   "is_active": true,
#   "balance": null
# }

๐Ÿ“ Importing the json Module

import json

Core functions:
- json.dump() โ€” save to a file
- json.dumps() โ€” convert to a string
- json.load() โ€” load from a file
- json.loads() โ€” parse from a string


๐Ÿ’พ Saving Data โ€” json.dump()

Saving simple data

import json

user = {
    "name": "Alice",
    "age": 25,
    "balance": 1000
}

# Open the file for writing and save
with open("user.json", "w", encoding="utf-8") as file:
    json.dump(user, file)

print("Data saved!")

What happens:
1. open("user.json", "w") โ€” opens the file for writing
2. json.dump(user, file) โ€” writes the dictionary to the file
3. File user.json is created!

Contents of user.json:

{"name": "Alice", "age": 25, "balance": 1000}

Pretty formatting โ€” indent

with open("user.json", "w", encoding="utf-8") as file:
    json.dump(user, file, indent=4, ensure_ascii=False)

Parameters:
- indent=4 โ€” indentation for readability
- ensure_ascii=False โ€” preserves non-ASCII characters

Result in the file:

{
    "name": "Alice",
    "age": 25,
    "balance": 1000
}

Much more readable! ๐Ÿ“–


๐Ÿ“‚ Loading Data โ€” json.load()

import json

# Open the file for reading and load
with open("user.json", "r", encoding="utf-8") as file:
    user = json.load(file)

print(user["name"])    # Alice
print(user["balance"]) # 1000

What happens:
1. Opens the file in read mode "r"
2. json.load(file) โ€” reads and converts to a Python dict
3. Work with the data like a regular dict!


๐Ÿ›ก๏ธ Safe Loading with try/except

Problem: The file might not exist!

import json

try:
    with open("user.json", "r", encoding="utf-8") as file:
        user = json.load(file)
    print("Data loaded!")
except FileNotFoundError:
    print("File not found! Creating a new profile.")
    user = {"name": "Stranger", "age": 0, "balance": 0}
except json.JSONDecodeError:
    print("File is corrupted! Using defaults.")
    user = {"name": "Stranger", "age": 0, "balance": 0}

print(user)

Error types:
- FileNotFoundError โ€” file doesn’t exist
- json.JSONDecodeError โ€” file is corrupted (invalid JSON)


๐Ÿ”„ Full Cycle: Save โ†’ Modify โ†’ Load

import json

# 1. Create data
user = {
    "name": "Alice",
    "balance": 1000,
    "transactions": []
}

# 2. Save
with open("account.json", "w", encoding="utf-8") as file:
    json.dump(user, file, indent=4, ensure_ascii=False)

print("Data saved!")

# 3. Load
with open("account.json", "r", encoding="utf-8") as file:
    loaded_user = json.load(file)

# 4. Modify
loaded_user["balance"] += 500
loaded_user["transactions"].append("deposit +500")

# 5. Save changes
with open("account.json", "w", encoding="utf-8") as file:
    json.dump(loaded_user, file, indent=4, ensure_ascii=False)

print("Changes saved!")

๐ŸŽฏ Example: Bank Account

import json

class BankAccount:
    def __init__(self, name, balance=0):
        self.name = name
        self.balance = balance
        self.transactions = []

    def deposit(self, amount):
        """Deposit funds."""
        self.balance += amount
        self.transactions.append(f"Deposit: +{amount}")
        print(f"Deposited: {amount}")

    def withdraw(self, amount):
        """Withdraw funds."""
        if amount > self.balance:
            print("Insufficient funds!")
            return

        self.balance -= amount
        self.transactions.append(f"Withdrawal: -{amount}")
        print(f"Withdrawn: {amount}")

    def save(self, filename):
        """Save the account to JSON."""
        data = {
            "name": self.name,
            "balance": self.balance,
            "transactions": self.transactions
        }

        with open(filename, "w", encoding="utf-8") as file:
            json.dump(data, file, indent=4, ensure_ascii=False)

        print(f"Account saved to {filename}")

    @staticmethod
    def load(filename):
        """Load an account from JSON."""
        try:
            with open(filename, "r", encoding="utf-8") as file:
                data = json.load(file)

            account = BankAccount(data["name"], data["balance"])
            account.transactions = data["transactions"]
            print(f"Account loaded from {filename}")
            return account

        except FileNotFoundError:
            print("File not found!")
            return None

# Usage
account = BankAccount("Alice", 1000)
account.deposit(500)
account.withdraw(200)
account.save("alice.json")

# Somewhere else in the program, or on the next run
loaded = BankAccount.load("alice.json")
print(f"Balance: {loaded.balance}")
print(f"History: {loaded.transactions}")

Contents of alice.json:

{
    "name": "Alice",
    "balance": 1300,
    "transactions": [
        "Deposit: +500",
        "Withdrawal: -200"
    ]
}

๐Ÿ“‹ Saving a List of Objects

Task: Save several accounts to a single file.

import json

accounts = [
    {"name": "Alice", "balance": 1000},
    {"name": "Bob", "balance": 500},
    {"name": "Charlie", "balance": 2000}
]

# Save
with open("bank.json", "w", encoding="utf-8") as file:
    json.dump(accounts, file, indent=4, ensure_ascii=False)

# Load
with open("bank.json", "r", encoding="utf-8") as file:
    loaded_accounts = json.load(file)

for account in loaded_accounts:
    print(f"{account['name']}: {account['balance']}")

Contents of bank.json:

[
    {
        "name": "Alice",
        "balance": 1000
    },
    {
        "name": "Bob",
        "balance": 500
    },
    {
        "name": "Charlie",
        "balance": 2000
    }
]

๐ŸŽฏ Pattern: Auto-Save

class BankAccount:
    def __init__(self, name, balance=0, filename=None):
        self.name = name
        self.balance = balance
        self.filename = filename or f"{name}.json"

    def _autosave(self):
        """Save automatically."""
        data = {"name": self.name, "balance": self.balance}
        with open(self.filename, "w", encoding="utf-8") as file:
            json.dump(data, file, indent=4, ensure_ascii=False)

    def deposit(self, amount):
        """Deposit with auto-save."""
        self.balance += amount
        self._autosave()  # Save after every change!
        print(f"Deposited: {amount}. Balance: {self.balance}")

    def withdraw(self, amount):
        """Withdraw with auto-save."""
        if amount <= self.balance:
            self.balance -= amount
            self._autosave()  # Save!
            print(f"Withdrawn: {amount}. Remaining: {self.balance}")

# Usage
account = BankAccount("Alice", 1000)
account.deposit(500)  # Auto-saved!
account.withdraw(200) # Auto-saved!

Benefits:
- โœ… Data is always up to date
- โœ… Won’t be lost on a crash
- โœ… No need to remember to call save()


๐Ÿ“ json.dumps() and json.loads() โ€” Working with Strings

dumps() โ€” to string

import json

data = {"name": "Alice", "age": 25}
json_string = json.dumps(data, ensure_ascii=False)

print(json_string)  # {"name": "Alice", "age": 25}
print(type(json_string))  # <class 'str'>

When to use:
- Sending data over a network
- Storing in a database
- Logging


loads() โ€” from string

import json

json_string = '{"name": "Bob", "balance": 500}'
data = json.loads(json_string)

print(data["name"])  # Bob
print(type(data))    # <class 'dict'>

When to use:
- Receiving data from an API
- Reading from a database
- Parsing configuration


โš ๏ธ What CANNOT Be Saved to JSON

โŒ Functions

data = {"func": print}  # Won't work!
json.dump(data, file)   # TypeError!

โŒ Class instances (directly)

class User:
    def __init__(self, name):
        self.name = name

user = User("Alice")
json.dump(user, file)  # TypeError: Object of type User is not JSON serializable

Solution: Convert to a dictionary first!

user_dict = {"name": user.name}
json.dump(user_dict, file)  # Works!

โŒ Sets

data = {"numbers": {1, 2, 3}}  # set is not supported
json.dump(data, file)  # TypeError!

# Solution: convert to a list
data = {"numbers": list({1, 2, 3})}

๐ŸŽฏ Pattern: Config File

import json

# config.json
# {
#   "app_name": "MyBank",
#   "version": "1.0",
#   "debug": true,
#   "max_accounts": 100
# }

def load_config(filename="config.json"):
    """Load configuration."""
    try:
        with open(filename, "r", encoding="utf-8") as file:
            return json.load(file)
    except FileNotFoundError:
        # Default values
        return {
            "app_name": "MyApp",
            "version": "1.0",
            "debug": False,
            "max_accounts": 10
        }

config = load_config()
print(f"App: {config['app_name']} v{config['version']}")

๐ŸŽฏ Pattern: JSON-Based Database

import json

class Database:
    def __init__(self, filename="database.json"):
        self.filename = filename
        self.data = self._load()

    def _load(self):
        """Load data."""
        try:
            with open(self.filename, "r", encoding="utf-8") as file:
                return json.load(file)
        except FileNotFoundError:
            return {}

    def _save(self):
        """Save data."""
        with open(self.filename, "w", encoding="utf-8") as file:
            json.dump(self.data, file, indent=4, ensure_ascii=False)

    def set(self, key, value):
        """Set a value."""
        self.data[key] = value
        self._save()

    def get(self, key, default=None):
        """Get a value."""
        return self.data.get(key, default)

    def delete(self, key):
        """Delete a value."""
        if key in self.data:
            del self.data[key]
            self._save()

# Usage
db = Database()
db.set("user_alice", {"balance": 1000, "age": 25})
db.set("user_bob", {"balance": 500, "age": 30})

alice = db.get("user_alice")
print(alice)  # {'balance': 1000, 'age': 25}

๐Ÿ”’ JSON Security

โš ๏ธ Never store passwords in plain text!

# โŒ Bad
user = {
    "login": "alice",
    "password": "12345"  # NEVER DO THIS!
}

# โœ… Good โ€” store a hash
import hashlib

password = "12345"
password_hash = hashlib.sha256(password.encode()).hexdigest()

user = {
    "login": "alice",
    "password_hash": password_hash
}

โšก Best Practices

โœ… Do:

  1. Use encoding=”utf-8” for non-ASCII characters
  2. Use indent=4 for readability
  3. Use ensure_ascii=False for non-ASCII text
  4. Wrap loads in try/except
  5. Validate data after loading
  6. Back up before overwriting

โŒ Don’t:

  1. Don’t store passwords in plain text
  2. Don’t serialize objects directly (use dicts/lists)
  3. Don’t forget encoding (you’ll get garbled text)
  4. Don’t ignore errors when loading

๐Ÿ“ Example: Full Banking System

import json

class Bank:
    def __init__(self, filename="bank_data.json"):
        self.filename = filename
        self.accounts = self._load_accounts()

    def _load_accounts(self):
        """Load all accounts."""
        try:
            with open(self.filename, "r", encoding="utf-8") as file:
                return json.load(file)
        except FileNotFoundError:
            return {}

    def _save_accounts(self):
        """Save all accounts."""
        with open(self.filename, "w", encoding="utf-8") as file:
            json.dump(self.accounts, file, indent=4, ensure_ascii=False)

    def create_account(self, name, initial_balance=0):
        """Create a new account."""
        if name in self.accounts:
            print("Account already exists!")
            return

        self.accounts[name] = {
            "balance": initial_balance,
            "transactions": []
        }
        self._save_accounts()
        print(f"Account {name} created! Balance: {initial_balance}")

    def deposit(self, name, amount):
        """Deposit funds."""
        if name not in self.accounts:
            print("Account not found!")
            return

        self.accounts[name]["balance"] += amount
        self.accounts[name]["transactions"].append(f"Deposit: +{amount}")
        self._save_accounts()
        print(f"Deposited: {amount}. Balance: {self.accounts[name]['balance']}")

    def withdraw(self, name, amount):
        """Withdraw funds."""
        if name not in self.accounts:
            print("Account not found!")
            return

        if amount > self.accounts[name]["balance"]:
            print("Insufficient funds!")
            return

        self.accounts[name]["balance"] -= amount
        self.accounts[name]["transactions"].append(f"Withdrawal: -{amount}")
        self._save_accounts()
        print(f"Withdrawn: {amount}. Remaining: {self.accounts[name]['balance']}")

    def show_account(self, name):
        """Display account information."""
        if name not in self.accounts:
            print("Account not found!")
            return

        account = self.accounts[name]
        print(f"\n=== Account: {name} ===")
        print(f"Balance: {account['balance']}")
        print("Transaction history:")
        for transaction in account["transactions"]:
            print(f"  - {transaction}")

# Usage
bank = Bank()
bank.create_account("Alice", 1000)
bank.deposit("Alice", 500)
bank.withdraw("Alice", 200)
bank.show_account("Alice")

# On the next run, data loads automatically!

๐ŸŽ“ Summary

JSON:
- โœ… A universal data storage format
- โœ… Human-readable
- โœ… Supported everywhere
- โœ… Built into Python

Core functions:
- json.dump(data, file) โ€” save to a file
- json.load(file) โ€” load from a file
- json.dumps(data) โ€” convert to a string
- json.loads(string) โ€” parse from a string

Golden rule: Always use try/except when loading, encoding="utf-8" for text, and indent=4 for readability!


Now your data won’t disappear when the program closes! ๐Ÿ’พโœจ

Your reaction to the article

๐Ÿ’ฌ Comments (0)

๐Ÿ” Sign in to leave a comment
๐Ÿšช Login
๐Ÿ’ญ

No comments yet

Be the first to share your opinion about this article!

๐Ÿ”— Similar

Similar articles

Continue learning with these materials

๐Ÿ“

Setting Up Your Environment: Python, pip, and VS โ€ฆ

Before writing code locally, you need to set up three tools: Python, pip, and VS...

๐Ÿ“… 04.06.2026 ๐Ÿ‘๏ธ 16
๐Ÿ“

Anthropic SDK: Getting Started with the Claude API

Anthropic Python SDK is the official library for working with Claude. It hides the complexity...

๐Ÿ“… 04.06.2026 ๐Ÿ‘๏ธ 16
๐Ÿ“

The datetime Module: Working with Dates and Times

datetime is Python's standard module for working with dates and times. It's part of the...

๐Ÿ“… 08.05.2026 ๐Ÿ‘๏ธ 66

Did you like the article?

Subscribe to our updates and receive new articles first. Grow with PyLand!