Python ve JSON doğal bir ikilidir. FastAPI veya Django ile REST API oluşturuyor, veri pipeline'ları işliyor ya da sadece bir yapılandırma dosyası okuyor olun — JSON ile sürekli çalışırsınız. İyi haber: Python'ın standart kütüphanesi ihtiyacınız olan her şeyi json modülünde sunar. Pip install gerekmez.

Gerçekten Kullandığınız Dört Fonksiyon

json modülü, günlük çalışma için size dört fonksiyon sunar:

  • json.loads(str) — JSON dizesini Python nesnesine dönüştürür
  • json.dumps(obj) — Python nesnesini JSON dizesine çevirir
  • json.load(file) — JSON'u doğrudan bir dosya nesnesinden ayrıştırır
  • json.dump(obj, file) — Python nesnesini JSON olarak bir dosyaya yazar

loads / dumps içindeki s harfi string (dize) anlamına gelir. s olmayan versiyonlar dosya nesneleriyle çalışır. Kuralı öğrendikten sonra hatırlaması kolaydır.

json.loads() — JSON Dizesini Ayrıştırma

python
import json

json_string = '{"name": "Alice", "age": 30, "active": true, "score": 98.5}'

user = json.loads(json_string)

print(user["name"])    # Alice
print(user["age"])     # 30
print(user["active"])  # True
print(type(user))      # <class 'dict'>

Tür eşlemesine dikkat edin: JSON true Python True olur, JSON false Python False olur, JSON null Python None olur. JSON nesneleri Python dict'e, JSON dizileri Python list'e dönüşür.

json.dumps() — JSON Dizesine Serileştirme

python
import json

user = {
    "name": "Bob",
    "age": 25,
    "roles": ["admin", "editor"],
    "active": True,
    "extra": None
}

# Kompakt (ağ iletimi için idealdir)
compact = json.dumps(user)
print(compact)
# {"name": "Bob", "age": 25, "roles": ["admin", "editor"], "active": true, "extra": null}

# Güzel biçimlendirilmiş (log ve insan okunabilirliği için idealdir)
pretty = json.dumps(user, indent=2)
print(pretty)
# {
#   "name": "Bob",
#   "age": 25,
#   "roles": [
#     "admin",
#     "editor"
#   ],
#   "active": true,
#   "extra": null
# }

Ters tür eşlemesine dikkat edin: Python True → JSON true, Python None → JSON null. Python bunu otomatik olarak halleder.

Dosyadan JSON Okuma

Bu muhtemelen en yaygın kullanım senaryosudur — başlangıçta bir yapılandırma veya veri dosyası okumak:

python
import json

# Tek adımda oku ve ayrıştır
with open("config.json", "r", encoding="utf-8") as f:
    config = json.load(f)

print(config["database"]["host"])  # localhost
print(config["database"]["port"])  # 5432

JSON dosyaları açarken her zaman encoding="utf-8" belirtin. JSON, RFC 8259 tarafından UTF-8 olarak tanımlanmıştır ve bu parametreyi atlarsanız, varsayılan kodlamanın bazen cp1252 olduğu Windows'ta sorunlara yol açabilir.

Dosyaya JSON Yazma

python
import json

results = {
    "timestamp": "2024-01-15T09:30:00Z",
    "total": 1523,
    "processed": 1521,
    "failed": 2,
    "errors": [
        {"id": 42, "reason": "missing field"},
        {"id": 99, "reason": "invalid format"}
    ]
}

with open("results.json", "w", encoding="utf-8") as f:
    json.dump(results, f, indent=2)

print("Results saved to results.json")

Hataları Doğru Şekilde İşleme

json.loads(), girdi geçerli JSON olmadığında json.JSONDecodeError (ValueError'ın bir alt sınıfı) hatası fırlatır. Kontrol etmediğiniz verileri ayrıştırırken her zaman bu hatayı yakalayın:

python
import json

def safe_parse(json_str):
    try:
        return json.loads(json_str)
    except json.JSONDecodeError as e:
        print(f"Invalid JSON at line {e.lineno}, column {e.colno}: {e.msg}")
        return None

data = safe_parse('{"name": "Alice"}')   # works fine
bad  = safe_parse('not json at all')     # prints error, returns None
also_bad = safe_parse('{"key": }')       # prints error with position info

JSONDecodeError size ayrıştırmanın başarısız olduğu tam satır ve sütunu verir; bu büyük JSON dosyalarında hata ayıklarken çok işe yarar.

Kullanışlı dumps() Seçenekleri

python
import json

data = {
    "z_key": 1,
    "a_key": 2,
    "price": 9.999999999
}

# Anahtarları alfabetik sırayla sırala (tekrarlanabilir çıktı / diff için idealdir)
print(json.dumps(data, sort_keys=True, indent=2))
# {
#   "a_key": 2,
#   "price": 9.999999999,
#   "z_key": 1
# }

# ASCII olmayan karakterlerin korunmasını sağla (varsayılan: \uXXXX olarak kaçırılır)
data2 = {"city": "Münich", "greeting": "こんにちは"}
print(json.dumps(data2, ensure_ascii=False))
# {"city": "Münich", "greeting": "こんにちは"}

# ensure_ascii=True ile (varsayılan):
print(json.dumps(data2))
# {"city": "M\u00fcnich", "greeting": "\u3053\u3093\u306b\u3061\u306f"}

ASCII olmayan metin içeren JSON dosyaları yazarken her zaman ensure_ascii=False eklerim. Kaçırılmış versiyon teknik olarak geçerli JSON'dur ancak bir metin editöründe okumak çok daha zordur.

Özel Nesneleri Serileştirme

Varsayılan olarak, json.dumps() özel sınıf örneklerini veya datetime nesnelerini serileştiremez. İki seçeneğiniz var: json.JSONEncoder'ı alt sınıflandırın ya da önce dict'e dönüştürün:

python
import json
from datetime import datetime, date

# Seçenek 1: özel encoder sınıfı
class AppEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, (datetime, date)):
            return obj.isoformat()
        return super().default(obj)

data = {"name": "Alice", "created_at": datetime(2024, 1, 15, 9, 30)}
print(json.dumps(data, cls=AppEncoder, indent=2))
# {
#   "name": "Alice",
#   "created_at": "2024-01-15T09:30:00"
# }

# Seçenek 2: default= parametresi (tek seferlik dönüşümler için daha basit)
print(json.dumps(data, default=str, indent=2))  # bilinmeyeni str'ye dönüştürür

Pratik Bir Desen: Yapılandırma Dosyası Yükleme

İşte neredeyse her Python projesinde kullandığım gerçek dünya deseni — makul varsayılanlarla JSON yapılandırma dosyası okuyan bir yapılandırma yükleyici:

python
import json
import os
from pathlib import Path

DEFAULTS = {
    "database": {"host": "localhost", "port": 5432},
    "debug": False,
    "log_level": "INFO"
}

def load_config(path="config.json"):
    config = DEFAULTS.copy()

    config_path = Path(path)
    if config_path.exists():
        with open(config_path, "r", encoding="utf-8") as f:
            try:
                user_config = json.load(f)
                # Derin birleştirme: kullanıcı ayarları varsayılanları geçersiz kılar
                for key, value in user_config.items():
                    if isinstance(value, dict) and key in config:
                        config[key].update(value)
                    else:
                        config[key] = value
            except json.JSONDecodeError as e:
                print(f"Warning: config.json is invalid ({e.msg}), using defaults")

    return config

config = load_config()
print(config["database"]["host"])  # localhost (or overridden value)

Özet

Python'ın json modülü hiçbir bağımlılık olmadan ihtiyacınız olan her şeyi karşılar. Temel kurallar: dizeler için loads()/dumps(), dosyalar için load()/dump() kullanın; dış veriyi ayrıştırırken her zaman JSONDecodeError'u işleyin ve veriniz Latin dışı karakterler içeriyorsa ensure_ascii=False ekleyin. JSON verilerini hata ayıklamak için JSON Formatter ve JSON Validator size çok zaman kazandırabilir.