JSON'dan CSV'ye Nasıl Dönüştürülür? Kaçış Karakterleri ve Tuzaklar
JSON’dan CSV’ye dönüştürme, düz nesnelerden oluşan bir JSON dizisini alıp satır satır bir tabloya çevirmektir: her nesne bir satır, her benzersiz anahtar bir sütun olur. İşin can alıcı noktası dönüşümün kendisi değil, kaçış kurallarıdır: bir değerin içinde virgül, tırnak işareti ya da satır sonu varsa, o değeri olduğu gibi yazamazsınız, yoksa sütunlar kayar ve tablo bozulur.
CSV, yıllardır “eski” ilan edilmesine rağmen hâlâ her yerde. Excel ve Google E-Tablolar dosyayı çift tıklamayla açar, veri işlem hatlarının çoğu (ETL script’leri, toplu içe aktarma araçları, muhasebe yazılımları) CSV’yi ortak payda olarak kabul eder ve JSON döndüren bir API’den gelen veriyi bir muhasebeciye ya da bir eski sisteme aktarmanız gerektiğinde CSV hâlâ en az sürtünmeli format. Sorun, JSON’un iç içe yapılar ve diziler taşıyabilmesine karşılık CSV’nin düz, iki boyutlu bir tablo olması: bu ikisi arasında bire bir eşleme yok, dönüştürücü bir karar vermek zorunda kalıyor.
Somut bir örnek üzerinden: escaping nasıl çalışır
Aşağıdaki JSON dizisini ele alalım, üç ürün kaydı:
[
{ "sku": "A100", "product": "Wireless Mouse, Black", "price": 19.99, "in_stock": true },
{ "sku": "A101", "product": "17\" Laptop Stand", "price": 42.5, "in_stock": false },
{ "sku": "A102", "product": "USB-C Cable", "price": 8.99, "in_stock": true }
]
Bu, aracın ürettiği CSV çıktısı:
sku,product,price,in_stock
A100,"Wireless Mouse, Black",19.99,true
A101,"17"" Laptop Stand",42.5,false
A102,USB-C Cable,8.99,true
Sütun başlıkları sku, product, price, in_stock sırasıyla geliyor, çünkü araç anahtarları dizideki ilk görüldükleri sırayla toplar, sadece ilk nesneye bakıp durmaz. Şimdi satır satır neden böyle göründüğüne bakalım.
İlk satırda Wireless Mouse, Black değeri bir virgül içeriyor. CSV’de virgül sütun ayracı olduğu için, değerin içindeki virgül ayraçla karışmasın diye tüm değer çift tırnak içine alınıyor: "Wireless Mouse, Black". Tırnak olmasaydı ayrıştırıcı bunu iki ayrı sütun sanırdı.
İkinci satırdaki 17" Laptop Stand biraz daha ilginç: değerin içinde tek bir çift tırnak karakteri var (17 inç anlamındaki "). RFC 4180 kuralı burada iki şey yapıyor aynı anda. Önce değerin içindeki her " karakteri ikiye katlanıyor (" → ""), sonra da değerin tamamı bir dış tırnak çiftiyle sarılıyor. Sonuç: "17"" Laptop Stand". İlk ve son tırnak dış sarmalayıcı, ortadaki çift tırnak ise kaçışa uğratılmış tek bir karakter. Bir CSV ayrıştırıcı bunu okurken “dış tırnak içindeyim, "" gördüm, bu kaçışa uğratılmış bir tırnak, tek bir " olarak sakla” mantığıyla geri çözer.
Üçüncü satırdaki USB-C Cable ise ne virgül, ne tırnak, ne de satır sonu içeriyor, bu yüzden hiçbir işleme uğramadan olduğu gibi yazılıyor. Kural basit: bir değer virgül, çift tırnak ya da satır sonu içeriyorsa tırnaklanır (ve içindeki tırnaklar ikiye katlanır); içermiyorsa dokunulmadan geçer.
Eksik anahtarlar: sütun birleşimi nasıl oluşuyor
Gerçek API yanıtlarında her nesne aynı alanlara sahip olmaz. Örneğin:
[
{ "name": "Ayşe", "city": "Ankara" },
{ "name": "Mehmet", "city": "Izmir", "country": "Turkiye" }
]
Buradaki sütun başlıkları name, city, country olur, ikinci nesnede ortaya çıkan country de dahil edilir. Ama ilk satırda country yok, o yüzden o hücre boş bırakılır, hata verilmez:
name,city,country
Ayse,Ankara,
Mehmet,Izmir,Turkiye
Bazı basit dönüştürücüler sadece ilk nesnenin anahtarlarına bakar ve sonraki nesnelerdeki fazladan alanları sessizce atar; burada kullanılan mantık böyle değil, dizideki tüm nesneleri tarayıp anahtarların birleşimini (union) çıkarır, hangi nesnede ilk göründüyse o sırayla.
Aracı deneyin
Kendi JSON’unuzu aşağıya yapıştırın, CSV çıktısını anında görün. Dönüşüm tamamen tarayıcınızda çalışır, veri hiçbir sunucuya gönderilmez.
Sık yapılan hatalar
İç içe nesneler [object Object] haline gelir. JSON’da bir değer başka bir nesne olabilir, ama CSV’nin böyle bir kavramı yok. Örneğin { "name": "Ayse", "address": { "city": "Ankara", "zip": "06100" } } gibi bir kayıt dönüştürüldüğünde, address sütununun altında [object Object] metni yazar, çünkü nesne JavaScript’in varsayılan metne çevirme kuralıyla stringe dönüştürülür ve içindeki city/zip bilgisi kaybolur. Çözüm, dönüştürmeden önce nesneyi düzleştirmek: address alanını kaldırıp yerine address_city: "Ankara" ve address_zip: "06100" gibi iki ayrı üst düzey anahtar koymak. Bu işlemi elle ya da bir düzleştirme fonksiyonuyla, dönüştürme aracına vermeden önce yapmanız gerekiyor.
Diziler ayrı sütunlara değil, tek bir hücreye sıkışır. "tags": ["red", "blue"] gibi bir alan CSV’ye çevrilirken, dizi elemanları ayrı sütunlara “patlamaz”. Bunun yerine dizi virgülle birleştirilmiş tek bir metne dönüşür: red,blue. Bu metnin kendisi artık bir virgül içerdiği için, escaping kuralı devreye girer ve hücre otomatik olarak tırnaklanır: "red,blue". Sonuç doğru okunur ama beklediğiniz gibi tags_1, tags_2 şeklinde ayrı sütunlar oluşmaz, her zaman tek bir sütunda virgülle ayrılmış liste olarak durur.
Excel’de sütunların hepsi A hücresine sıkışması. Türkçe Excel, ondalık ayıracı olarak virgül kullandığı için liste ayıracı (list separator) olarak noktalı virgülü bekler. Standart, virgülle ayrılmış bir CSV dosyasını Türkçe yerel ayarlı bir Excel’de doğrudan açtığınızda, Excel virgülü ayraç olarak tanımaz ve tüm satırı tek bir A sütununa yığar. Bunu düzeltmenin iki yolu var: Excel’de “Veri > Metni Sütunlara Dönüştür” seçeneğini kullanıp ayraç olarak virgülü elle seçmek, ya da işletim sisteminin bölge ayarlarından liste ayıracını noktalı virgülden virgüle çevirmek. Bu araç şu an sadece virgül ayraçlı çıktı üretiyor, noktalı virgül seçeneği yok, bu yüzden Türkçe Excel’e aktarırken bu adımı akılda tutmak gerekiyor.
Girdi bir dizi olmalı, tek bir nesne değil. Araç [{...}, {...}] formatında bir dizi bekler. Köşeli parantezleri unutup sadece { "sku": "A100", "product": "Mouse" } yapıştırırsanız, bu geçerli bir nesne olsa da dizi olmadığı için araç bunu kabul etmez ve satır içi bir hata gösterir, sayfa çökmez. Tek bir kaydı dönüştürmek istiyorsanız bile onu [ ] içine sarmanız gerekir: [{ "sku": "A100", "product": "Mouse" }]. Aynı şekilde bozuk JSON (eksik virgül, kapanmamış tırnak) da hata olarak bildirilir, sessizce yanlış bir çıktı üretmez.
Sıkça sorulan sorular
JSON’daki iç içe bir nesneyi CSV’ye çevirmeden önce ne yapmalıyım?
Nesneyi düzleştirin. address: { city, zip } gibi bir alanı, address_city ve address_zip gibi iki ayrı üst düzey anahtara bölün. Düzleştirmeden dönüştürürseniz o sütunda [object Object] metni görürsünüz ve asıl veri kaybolur.
JSON içindeki bir dizi alan CSV’de ayrı sütunlara mı bölünür?
Hayır. ["red", "blue"] gibi bir dizi, virgülle birleştirilmiş tek bir metin hücresine dönüşür (red,blue), bu metin bir virgül içerdiği için otomatik olarak tırnaklanır ("red,blue"). Elemanları gerçekten ayrı sütunlarda görmek istiyorsanız, veriyi dönüştürmeden önce kendiniz tags_1, tags_2 gibi ayrı alanlara bölmeniz gerekir.
Çıktı CSV’yi Türkçe Excel’de açtığımda neden her şey tek bir sütuna yığılıyor? Türkçe yerel ayarlı Excel, ondalık ayıracı virgül olduğu için liste ayıracı olarak noktalı virgül bekler, oysa bu araç standart virgül ayraçlı CSV üretir. Çözüm için Excel’de “Veri > Metni Sütunlara Dönüştür” ile ayracı elle virgül olarak seçin, ya da işletim sisteminin bölge ayarlarından liste ayıracını değiştirin.
Tek bir JSON nesnesini de bu araçla CSV’ye çevirebilir miyim?
Evet, ama köşeli parantez içine almanız gerekir. Araç bir dizi bekler, tek bir nesneyi ({ "sku": "A100" }) doğrudan yapıştırırsanız kabul edilmez. Onu [{ "sku": "A100" }] şeklinde bir dizinin tek elemanı olarak yazmanız yeterli, sonuç tek satırlık bir CSV olur.
Her nesnede aynı anahtarlar yoksa sütunlar nasıl belirleniyor? Sütun başlıkları, dizideki tüm nesnelerin anahtarlarının birleşimidir, sadece ilk nesneye bakılmaz. Bir nesnede olmayan bir anahtar başka bir nesnede varsa, o sütun yine de eklenir ve eksik olan nesnenin hücresi boş bırakılır, hata verilmez.
Dönüştürme sırasında verim bir sunucuya gönderiliyor mu? Hayır. Dönüşüm tamamen tarayıcınızda, JavaScript ile yapılır. Yapıştırdığınız JSON hiçbir zaman pluri.tools sunucularına ya da başka bir yere gönderilmez, bu yüzden hassas veya gizli veriler için de güvenle kullanabilirsiniz.