İçeriğe geç

Menü

Berk Akademi
Yorumlar Google yorumları Birebir ders başvurusu Ücretsiz ön görüşme Ana Sayfa

Python JSON Verisi Nasıl CSV'ye Çevrilir? Liste ve Sözlük Örneği

python-json-csv-ye-cevirme
Bu yazıda neler var?
  1. JSON ve CSV Neden Birebir Karşılık Gelmez?
  2. Üç JSON Yapısında Sütunlar Nasıl Belirlenir?
  3. Ürün Listesini CSV'ye Çeviren Çalışan Örnek
  4. Eksik ve Fazla Alanlar: restval ve extrasaction
  5. İç İçe JSON Alanları: Düzleştirme ya da Tek Hücrede Birleştirme
  6. Türkçe Karakterler İçin encoding ve newline Ayarları
  7. Dönüşümü Doğrulama, Sık Hatalar ve Pandas Notu

Python'da JSON verisini CSV'ye çevirmek için önce JSON'u json.loads ya da json.load ile Python nesnesine okursun. Kayıtlar sözlük listesi olarak gelir ve sözlük anahtarları CSV sütunlarına karşılık gelir. Sonra csv.DictWriter ile başlık satırını ve kayıtları dosyaya yazarsın. Tek sözlük gelirse onu [veri] biçiminde listeye sararak aynı yolu izlersin.

JSON ve CSV Neden Birebir Karşılık Gelmez?

JSON hiyerarşiktir. Bir nesnenin içinde başka bir nesne ya da liste durabilir, kayıtlar farklı anahtarlar taşıyabilir. CSV ise satır ve sütun tabanlı düz bir metin biçimidir. Her satır aynı sütun düzenine uyar ve her hücre yalnızca bir metin değeri taşır. Bu iki biçim aynı veri modeli değildir. Bu yüzden dönüşümde önce sütunlar belirlenir, sonra kayıtlar yazılır.

Bu farkın somut sonuçları var. İç içe bir alanı olduğu gibi tek hücreye sığdıramazsın. CSV'de her değer metin olarak saklanır, dolayısıyla JSON'daki sayı, true ve null gibi tür bilgileri dosyada ayrışmaz. Sütun listene almadığın alanlar çıktıda yer almaz. Dönüşümün hangi noktada bilgi kaybettirdiğini baştan bilmek gerekir.

Dönüşüm üç adımdan oluşur:

  1. JSON'u Python nesnesine oku: dosyadan okuyorsan json.load (dosya nesnesi alır), elindeki bir metinden okuyorsan json.loads kullanılır.
  2. Sütun adlarını belirle: hangi anahtarlar başlık satırını oluşturacak, karar ver.
  3. Satırları yaz: csv.DictWriter ile başlığı ve kayıtları dosyaya aktar.

Üç JSON Yapısında Sütunlar Nasıl Belirlenir?

Üç JSON Yapısında Sütunlar Nasıl Belirlenir?

Karşına çıkan JSON genellikle üç biçimden birindedir. Her biri için sütun belirleme yolu ve olası veri kaybı farklıdır.

JSON yapısıCSV'de karşılığıSütunlar nasıl belirlenirDikkat edilecek veri kaybı
Tek sözlükListeye sarılınca tek satırSözlüğün anahtarları sütun olurKayıp yok; yalnızca değerler metne dönüşür
Sözlük listesi (ana senaryo)Her sözlük bir satırSabit liste ya da tüm anahtarların birleşimiSabit listede olmayan alanlar dışarıda kalır
İç içe alanlarDüzleştirilmiş sütunlar ya da tek hücrede birleştirilmiş listeİç anahtarlar birleştirilerek yeni sütun adı üretilirListe birleştirilince öğeler tek metne dönüşür, yapı kaybolur

Sözlük listesinde iki yoldan birini seçersin. Sabit sütun listesi: sütunları kendin yazarsın, çıktı öngörülebilir olur, istemediğin alanlar dışarıda kalır. Anahtar birleşimi: tüm kayıtlardaki anahtarları toplarsın, hiçbir alan kaybolmaz. Ancak kayıtlar farklı anahtarlar taşıyorsa bazı hücreler boş kalır.

Python'ın güncel sürümlerinde sözlükler anahtarları ekleme sırasıyla tutar. dict.fromkeys bu özellikten yararlanarak anahtarları ilk görülme sırasıyla, tekrar etmeden toplar:

kayitlar = [
    {"ad": "Defter", "fiyat": 45.5},
    {"ad": "Kalem", "renk": "mavi"},
    {"ad": "Silgi", "fiyat": 10, "renk": "beyaz"},
]

sutunlar = list(dict.fromkeys(anahtar for kayit in kayitlar for anahtar in kayit))
print(sutunlar)

Beklenen çıktı:

['ad', 'fiyat', 'renk']

Aynı işi küme (set) ile yaparsan tekrarlar elenir ama sütun sırası güvence altında olmaz. Dosyayı her çalıştırışta başlık sırası değişebilir, bu yüzden sıralı birikim tercih edilir. Sütunları belirlemek aslında küçük bir algoritma sorusudur: veriyi tara, görülenleri sırayla biriktir, tekrarı ele. Bu tür adım adım çözüm kurma becerini ölçmek istersen dilden bağımsız çalışan Algoritmik Düşünme Testi iyi bir başlangıç olabilir.

Ürün Listesini CSV'ye Çeviren Çalışan Örnek

Örnekte kurgusal ürün verisi kullanıyoruz. Fiyatlar tamamen uydurmadır. JSON metni bir Python metni olarak elimizde olduğu için json.loads ile okuyoruz:

import csv
import json

json_metin = """[
  {"urun_adi": "Defter", "kategori": "Kırtasiye", "fiyat": 45.5},
  {"urun_adi": "Kalem Seti", "kategori": "Kırtasiye", "fiyat": 32.0},
  {"urun_adi": "Sırt Çantası", "kategori": "Çanta", "fiyat": 399.9},
  {"urun_adi": "Su Matarası", "kategori": "Aksesuar", "fiyat": 85.0}
]"""

urunler = json.loads(json_metin)
alanlar = ["urun_adi", "kategori", "fiyat"]

with open("urunler.csv", "w", newline="", encoding="utf-8") as dosya:
    yazici = csv.DictWriter(dosya, fieldnames=alanlar)
    yazici.writeheader()
    yazici.writerows(urunler)

Oluşan urunler.csv dosyası şöyle görünür:

urun_adi,kategori,fiyat
Defter,Kırtasiye,45.5
Kalem Seti,Kırtasiye,32.0
Sırt Çantası,Çanta,399.9
Su Matarası,Aksesuar,85.0

Kodu satır satır okuyalım:

  • json.loads(json_metin) metni Python'da sözlük listesine çevirir.
  • alanlar sütun adlarını ve sırasını belirler. Bu, sabit sütun listesi yoludur.
  • newline="" csv modülünün satır sonlarını kendisinin yönetmesi için açılış parametresidir. encoding="utf-8" ile dosya UTF-8 olarak yazılır. Türkçe karakterlerin Excel'de doğru açılması için gereken ayarları ilerleyen bölümde ayrıca ele alacağız.
  • DictWriter her sözlüğü fieldnames sırasına göre satıra dizer.
  • writeheader() başlık satırını, writerows(urunler) listedeki tüm kayıtları yazar.

JSON bir dosyadaysa metin yerine dosya nesnesini json.load'a verirsin: with open("urunler.json", encoding="utf-8") as f: urunler = json.load(f). Sonrası aynıdır.

Tek sözlük gelirse

writerows bir kayıt listesi bekler. Elinde tek sözlük varsa onu [veri] biçiminde listeye sararsın:

tek = {"urun_adi": "Defter", "kategori": "Kırtasiye", "fiyat": 45.5}

with open("tek_urun.csv", "w", newline="", encoding="utf-8") as dosya:
    yazici = csv.DictWriter(dosya, fieldnames=list(tek))
    yazici.writeheader()
    yazici.writerows([tek])

Beklenen çıktı, başlık ve tek veri satırından oluşur:

urun_adi,kategori,fiyat
Defter,Kırtasiye,45.5

Burada sütun adlarını list(tek) ile sözlüğün kendi anahtarlarından aldık. Bu örnekte bilgi kaybı yok. Yine de 45.5 artık bir sayı olarak değil, dosyada metin olarak duruyor.

Eksik ve Fazla Alanlar: restval ve extrasaction

Gerçek JSON verisinde her kayıt aynı anahtarlara sahip olmayabilir. csv.DictWriter bu iki durumu farklı ele alır. Kayıtta eksik anahtar varsa hücre boş kalır ya da restval ile belirlediğin değer yazılır. Kayıtta fieldnames içinde olmayan fazladan anahtar varsa varsayılan davranış hata vermektir.

Eksik alan: restval

Python'un csv dokümantasyonuna göre restval varsayılan olarak boş metindir. Sözlükte fieldnames içindeki bir anahtar yoksa o hücreye bu değer yazılır.

import csv

urunler = [
    {"ad": "Defter", "fiyat": 45.5},
    {"ad": "Kalem"},  # fiyat alanı yok
]

with open("urunler.csv", "w", encoding="utf-8", newline="") as f:
    yazici = csv.DictWriter(f, fieldnames=["ad", "fiyat"], restval="YOK")
    yazici.writeheader()
    yazici.writerows(urunler)

Beklenen urunler.csv içeriği:

ad,fiyat
Defter,45.5
Kalem,YOK

restval vermezsen son satır Kalem, olur. Burada önemli bir sınır var: CSV'de boş hücre, "bu alan hiç yoktu" ile "değer boş metindi" ayrımını göstermez. İkisi de aynı görünür. Bu ayrım senin için önemliyse restval ile belirgin bir işaret seçebilirsin, ama gerçek verinde "YOK" metni de geçiyorsa karışıklık yine olabilir.

Fazla anahtar: extrasaction

extrasaction varsayılanı 'raise''dir. Sözlükte fieldnames dışında bir anahtar bulunursa ValueError oluşur.

fazla = [
    {"ad": "Defter", "fiyat": 45.5},
    {"ad": "Silgi", "fiyat": 10, "stok": 120},
]

with open("urunler.csv", "w", encoding="utf-8", newline="") as f:
    yazici = csv.DictWriter(f, fieldnames=["ad", "fiyat"])
    yazici.writeheader()
    yazici.writerows(fazla)

Hata mesajı şuna benzer: ValueError: dict contains fields not in fieldnames: 'stok'. Hata vermesi aslında bir koruma sağlar; veri yapısında beklemediğin bir değişiklik olduğunu sana haber verir.

extrasaction="ignore" verirsen fazla anahtarlar atlanır:

yazici = csv.DictWriter(f, fieldnames=["ad", "fiyat"], extrasaction="ignore")

Çıktı artık Defter,45.5 ve Silgi,10 satırlarını içerir. Dikkat: stok değeri CSV'ye hiç yazılmaz ve hiçbir uyarı görmezsin. Bu bir veri kaybıdır. Kaybın bilinçli olduğundan emin değilsen ignore kullanma.

Hangi durumda hangi seçenek?

  • Eksik alan normalse ve boş hücre yeterliyse: varsayılan restval yeterlidir.
  • Eksikliği görünür kılmak istiyorsan: restval="YOK" gibi bir işaret seç.
  • Tüm kayıtlarda aynı anahtarlar bekleniyorsa: extrasaction varsayılanı kalsın, hata yakalayıcı olarak işe yarar.
  • Fazla alanların CSV'de yer almaması bilinçli bir karar ise: extrasaction="ignore" kullan, kaybı kendin biliyor ol.
  • Fazla alanı da saklamak istiyorsan: fieldnames listesine o anahtarı ekle (tüm kayıtların anahtarlarını önceden tarayarak oluşturabilirsin).

İç İçe JSON Alanları: Düzleştirme ya da Tek Hücrede Birleştirme

İç İçe JSON Alanları: Düzleştirme ya da Tek Hücrede Birleştirme

CSV'de her hücre tek bir düz değer taşır. Bir kaydın içinde başka bir nesne ya da liste varsa bunu satır-sütun yapısına sığdırmak için bir karar vermen gerekir. Kurgusal bir ürün kaydı üzerinden iki yaklaşımı görelim:

urun = {
    "ad": "Kalem",
    "fiyat": 12.5,
    "tedarikci": {"ad": "Ege Kırtasiye", "sehir": "İzmir"},
    "etiketler": ["kalem", "okul"],
}

1. Düzleştirme

İç nesnenin alanlarını tedarikci_ad ve tedarikci_sehir gibi ayrı sütunlara taşırsın. Kayıt başına küçük bir yardımcı fonksiyon yeterlidir:

import csv

def duzlestir(u):
    return {
        "ad": u["ad"],
        "fiyat": u["fiyat"],
        "tedarikci_ad": u["tedarikci"]["ad"],
        "tedarikci_sehir": u["tedarikci"]["sehir"],
        "etiketler": ";".join(u["etiketler"]),
    }

satirlar = [duzlestir(urun)]
with open("urunler.csv", "w", encoding="utf-8", newline="") as f:
    yazici = csv.DictWriter(f, fieldnames=list(satirlar[0]))
    yazici.writeheader()
    yazici.writerows(satirlar)

Beklenen çıktı:

ad,fiyat,tedarikci_ad,tedarikci_sehir,etiketler
Kalem,12.5,Ege Kırtasiye,İzmir,kalem;okul

2. Liste değerini tek hücrede birleştirme

Yukarıdaki etiketler sütunu bu yöntemi kullanıyor: ";".join(...) listeyi tek metne çevirir. Bunun açık dezavantajları var:

  • Ayırıcı değerin içinde geçerse (ör. bir etiket "kalem;jel" ise) CSV'yi okuyan kişi öğeleri yanlış ayırır.
  • Geri dönüşüm otomatik değildir; listeyi geri elde etmek için split(";") gibi bir adımı sen yazmalısın.
  • Her şey metne dönüşür. Listedeki sayı, metin ve boş değer ayrımı kaybolur.
  • Boş liste ile hiç olmayan alan aynı boş hücreyle görünür.

Düzleştirmek istemezsen iç nesneyi json.dumps ile metne çevirip tek hücreye koyabilirsin; ancak hücre, CSV açısından yine yalnızca bir metindir.

İç içelik çok derinse ya da kayıtlar arasında düzensizse (bir kayıtta üç, diğerinde yedi seviye gibi) CSV doğru araç olmayabilir. Bu durumda verinin JSON olarak kalması çoğu zaman daha dürüst bir seçimdir.

Türkçe Karakterler İçin encoding ve newline Ayarları

CSV yazarken open("dosya.csv", "w", encoding="utf-8", newline="") kalıbını kullan. encoding="utf-8" ş, ğ, ı, İ, ö, ü, ç gibi karakterlerin bozulmadan yazılmasını sağlar. Açıkça vermezsen Python sistemin varsayılan kodlamasını kullanır ve bu makineden makineye değişebilir.

newline="" ise Python'un csv dokümantasyonunda önerilen bir ayardır. Satır sonlarını csv modülü kendisi yönetir; bu ayarı vermezsen bazı sistemlerde satırlar arasında boş satırlar oluşabilir.

import csv

urunler = [{"ad": "Çığlık Işığı", "fiyat": 99.9}, {"ad": "Şeker Ğ", "fiyat": 5}]

with open("tr.csv", "w", encoding="utf-8", newline="") as f:
    yazici = csv.DictWriter(f, fieldnames=["ad", "fiyat"])
    yazici.writeheader()
    yazici.writerows(urunler)

with open("tr.csv", encoding="utf-8", newline="") as f:
    for satir in csv.DictReader(f):
        print(satir["ad"], satir["fiyat"])

Beklenen çıktı:

Çığlık Işığı 99.9
Şeker Ğ 5

Dosyayı csv.DictReader ile geri okumak, yazdıklarını hızlıca kontrol etmenin kolay yoludur. JSON dosyasını okurken de open("veri.json", encoding="utf-8") ver. json.dump tarafındaki ensure_ascii ayarı okuma için sorun yaratmaz; json.load hem kaçış dizilerini hem doğrudan yazılmış Türkçe karakterleri aynı biçimde çözer.

Excel'de karakterler bozuk görünürse

Excel, BOM içermeyen UTF-8 CSV dosyasını sürüme ve ayara göre farklı açabilir. Dosyayı Excel'de açtığında Türkçe karakterler bozuk görünüyorsa encoding="utf-8-sig" ile yazmayı deneyebilirsin. Bu kodlama dosyanın başına bir BOM işareti ekler. Her durumda gerekli değildir; ayrıca BOM'u tanımayan bazı araçlarda ilk sütun adının başında görünmez bir karakter belirebilir. Dosyayı Excel dışında da kullanacaksan iki sürümü de deneyip sonucu karşılaştır.

Dönüşümü Doğrulama, Sık Hatalar ve Pandas Notu

CSV dosyası oluştu diye dönüşüm doğru sayılmaz. Veri kaybı çoğu zaman hata vermeden sessizce olur. Dosyayı kapatmadan önce şu kontrol listesinden geçebilirsin:

  • Sütun listesi (fieldnames) kayıtlardaki anahtarlarla uyumlu mu?
  • Eksik alanlar restval ile bilinçli bir değere mi çevrildi?
  • Fazla anahtarlar extrasaction="ignore" ile atıldıysa, bu veri kaybını bilerek mi kabul ettin?
  • İç içe alanlar düzleştirildi mi, yoksa tek hücrede mi birleştirildi?
  • Dosya encoding ve newline="" ayarlarıyla mı açıldı?
  • CSV'deki satır sayısı JSON'daki kayıt sayısına eşit mi?

Son maddeyi kısa bir kodla denetleyebilirsin. DictReader başlık satırını saymadığı için karşılaştırma doğrudan yapılır:

import json, csv

with open("urunler.json", encoding="utf-8") as f:
    kayitlar = json.load(f)

with open("urunler.csv", encoding="utf-8-sig", newline="") as f:
    satirlar = list(csv.DictReader(f))

print(len(kayitlar), len(satirlar))

Beklenen çıktı, JSON'da üç ürün varsa 3 3 olur. İki sayı farklıysa yazma döngüsünü ve filtreleri kontrol et.

Sık karşılaşılan hatalar

  • ValueError: DictWriter, fieldnames içinde olmayan bir anahtar bulduğunda varsayılan ayarla bu hatayı verir. Sütunu listeye ekle ya da veri kaybını bilerek extrasaction="ignore" ile kabul et.
  • json.JSONDecodeError: Dosya geçerli JSON değildir; örneğin sondaki fazladan virgül ya da tek tırnak buna yol açar. Bu sınıf ValueError'ın alt sınıfıdır, bu yüzden except ValueError da onu yakalar.
  • Liste yerine sözlük gelmesi: Kök nesne tek bir sözlükse [veri] ile listeye sar. Kayıtlar bir anahtarın altındaysa veri["urunler"] gibi o listeyi seç.

Pandas hakkında kısa not

Büyük ve düzensiz verilerde pandas ile de aynı dönüşümü yapabilirsin. Bu yazı standart kütüphanede kaldı, çünkü sütunların nasıl seçildiğini ve verinin nerede kaybolabileceğini adım adım görmek için önce bu yol önerilir. Mantığı oturttuktan sonra pandas'a geçmek daha rahat olur. Kendi düzeyini ölçmek istersen ücretsiz Python bilgi testini çözebilirsin.

Bir dönüşümü iki kez kontrol etmek, üç satırlık bir veriyle başlayıp yüzlerce kayda geçerken seni sürprizlerden korur.

Bu içerik aradığın cevabı verdi mi?
Yanıtın, hangi yazıları geliştirmemiz gerektiğini anlamamıza yardımcı olur.
Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

Bu konudan sonra ne okuyabilirsin?

Tüm yazılar

İlgili Eğitimler

Berk Keskin, yazılım geliştirici ve eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; İzmir Ekonomi Üniversitesi'ni bölüm birincisi ve yüksek şeref öğrencisi olarak tamamladı. Bugün yalnızca eğitim vermekle kalmıyor, sektörde aktif olarak yazılım projeleri geliştiriyor ve gerçek dünya deneyimini birebir derslerine taşıyor. Ezberden uzak, mühendislik zihniyetini merkeze alan sürdürülebilir öğrenme sistemleri tasarlayarak sorgulayan, üreten ve problem çözebilen yeni nesil yazılımcılar yetiştiriyor.

Sektörel Deneyim & Projeler

  • Ticarify Entegrasyon Yazılım logosu CEO Ticarify Entegrasyon YazılımPazaryerleri ve e-ticaret sitelerine otomatik e-fatura kesimi, sipariş ve kargo takibi hizmetleri sunan e-Dönüşüm platformunun API mimarisini ve yazılım ekibini yönetmektedir.
  • Benim Düğünüm logosu CEO Benim DüğünümDijital etkinlik ve anı paylaşım platformu.
  • Siberdizayn logosu Yazılım Ekibi Lideri SiberdizaynYüksek anlık oyuncu trafiğine sahip oyun kontrol panelleri ve sunucu altyapıları geliştiren yazılım ekibine liderlik etmektedir.
  • MEDYOGRAFYA 360° Dijital Çözümler logosu Dijital Strateji Lideri MEDYOGRAFYA 360° Dijital ÇözümlerŞirketlerin dijital çözümlerde uzun vadede nasıl ilerlemesi gerektiği ve dijital dönüşüm süreçlerinin yönetilmesine destek olmaktadır.
  • İzmir Ekonomi Üniversitesi logosu Danışma Kurulu Üyesi İzmir Ekonomi ÜniversitesiMezun olduğu üniversitesinde, Bilgisayar Programcılığı bölümünün akademik müfredatını güncel sektör ihtiyaçlarına göre şekillendirmek adına Danışma Kurulu'nda görev almaktadır.
WhatsApp Hemen Ara