JSON Nedir? Sözdizimi, Veri Tipleri ve Sık Yapılan Hatalar

Geliştirici · · 8 dk okuma · Sorgulaa Editör Ekibi

JSON nedir ve neden her yerde?

JSON (JavaScript Object Notation), yapılandırılmış veriyi düz metin olarak ifade etmeye yarayan hafif bir veri biçimidir. Bir programın bellekte tuttuğu nesneleri, listeleri ve değerleri, başka bir programın kolayca okuyabileceği bir metne dönüştürür. Adında JavaScript geçse de dile bağımlı değildir: Python, PHP, Java, Go, C# ve akla gelen hemen her dil JSON okuyup yazabilir. Bugün bir mobil uygulama sunucudan veri çektiğinde, bir ödeme sistemi bildirim gönderdiğinde ya da bir geliştirme aracı ayar dosyasını okuduğunda, arka planda büyük olasılıkla JSON dolaşır.

Biçim, 2000'lerin başında Douglas Crockford tarafından JavaScript'in nesne yazımından esinlenerek tanımlanıp yaygınlaştırıldı; sonrasında ECMA-404 ve RFC 8259 belgeleriyle standartlaştırıldı. Başarısının sırrı sadeliğindedir: dilbilgisinin tamamı tek bir sayfaya sığar, insan gözüyle okunabilir ve ayrıştırıcı yazmak kolaydır. Ancak bu sadelik katı kurallarla birlikte gelir. JSON "aşağı yukarı doğru" olamaz; tek bir fazladan virgül bütün belgeyi geçersiz kılar. Bu rehber, kuralları, veri tiplerini, benzer biçimlerle farkları ve pratikte en çok can yakan hataları ele alıyor.

Sözdiziminin temel kuralları

JSON iki yapı taşı üzerine kuruludur: nesne ve dizi. Nesne, süslü parantezler içinde yazılan anahtar-değer çiftleridir; dizi ise köşeli parantezler içinde sıralı bir değer listesidir. Küçük bir örnek:

{ "ad": "Ayşe", "yas": 34, "aktif": true, "etiketler": ["editör", "yönetici"], "adres": { "il": "İzmir", "postaKodu": "35000" }, "telefon": null }

Bu tek satırda biçimin neredeyse bütün kuralları görülür:

  • Anahtarlar her zaman çift tırnak içinde yazılan metinlerdir. Tırnaksız ya da tek tırnaklı anahtar geçersizdir.
  • Anahtar ile değer arasına iki nokta, çiftler ve dizi elemanları arasına virgül konur.
  • Son elemandan sonra virgül konmaz.
  • Değerler iç içe geçebilir: nesnenin içinde dizi, dizinin içinde nesne olabilir; derinlik için biçimsel bir sınır yoktur.
  • Boşluk, sekme ve satır sonları değerlerin dışında serbesttir; ayrıştırıcı bunları yok sayar. Belgeyi tek satıra sıkıştırmak da girintili yazmak da aynı veriyi ifade eder.
  • Bir JSON belgesinin kökü çoğunlukla nesne ya da dizidir; güncel standart tek başına bir metin, sayı ya da true gibi bir değerin de geçerli bir belge olmasına izin verir.

Standart, veri alışverişinde karakter kodlaması olarak UTF-8'i öngörür. Bu sayede Türkçe karakterler olduğu gibi yazılabilir; "ş" ya da "ğ" için özel bir kaçış dizisi kullanmak gerekmez.

Altı veri tipi

JSON'da tam olarak altı tür değer vardır. Listenin kısa olması bilinçli bir tasarım kararıdır: her dilde karşılığı bulunan en küçük ortak kümeyi hedefler.

TipÖrnekDikkat edilecek nokta
Metin (string)"Merhaba"Yalnızca çift tırnak; içerideki çift tırnak ve ters bölü kaçışlanır
Sayı (number)42, -3.14, 1.5e10Başta gereksiz sıfır, artı işareti, onaltılık yazım, NaN ve Infinity yok
Mantıksal (boolean)true, falseKüçük harfle ve tırnaksız yazılır
Boş değernullKüçük harfle; "bilinçli olarak boş" anlamına gelir
Nesne (object){ "a": 1 }Anahtarlar metin olmalı; aynı anahtarın tekrarı sorun çıkarır
Dizi (array)[1, "iki", null]Sıralıdır; farklı tipte elemanlar içerebilir

Metinlerde kaçış dizileri

Bir metnin içinde çift tırnak kullanmak gerekiyorsa önüne ters bölü konur: "O bana \"gel\" dedi" gibi. Ters bölünün kendisi \\, satır sonu \n, sekme \t olarak yazılır; herhangi bir Unicode karakteri \u ve dört onaltılık haneyle ifade edilebilir. Ham satır sonu ve sekme gibi kontrol karakterleri metnin içine doğrudan konamaz. Windows dosya yollarını JSON'a yazarken ters bölüleri çiftlemeyi unutmak, en sık görülen kaçış hatasıdır.

Olmayan tipler: tarih, ondalık para, ikili veri

JSON'da tarih tipi yoktur. Yaygın uygulama, tarihleri ISO 8601 biçiminde metin olarak taşımaktır: "2025-03-14T09:30:00Z" gibi. Saat dilimini belirtmemek, farklı sunucularda farklı yorumlanan tarihlerin baş nedenidir. Resim ve dosya gibi ikili veriler de doğrudan konamaz; bunlar genellikle Base64 ile metne çevrilerek bir string alanında taşınır, bu da boyutu yaklaşık üçte bir oranında büyütür. Para tutarlarında ise ondalıklı sayı yerine kuruş cinsinden tam sayı ya da metin kullanmak, kayan nokta yuvarlama hatalarından kaçınmanın güvenli yoludur.

JSON, XML ve YAML karşılaştırması

Üç biçim de yapılandırılmış veriyi metin olarak taşır, ama farklı ihtiyaçlar için tasarlanmıştır.

ÖzellikJSONXMLYAML
YazımParantez ve tırnak tabanlı, kısaAçılan-kapanan etiketler, uzunGirinti tabanlı, en sade görünüm
Yorum satırıYokVarVar
Veri tipleriAltı yerleşik tipHer şey metin; tipler şema ile tanımlanırZengin, ancak örtük tip dönüşümleri sürpriz yaratabilir
Şema ve doğrulamaJSON SchemaXSD, DTD; olgun ve güçlüGenellikle JSON Schema ile
Tipik kullanımWeb API'leri, veri alışverişiKurumsal entegrasyon, belge biçimleri, e-fatura gibi resmî standartlarYapılandırma dosyaları, dağıtım tanımları

XML, nitelikler, ad alanları ve karışık içerik (metin içinde etiket) gibi JSON'da karşılığı olmayan yeteneklere sahiptir; belge ağırlıklı işlerde hâlâ güçlüdür. Aynı veriyi XML ile yazmak, her alan için açılış ve kapanış etiketi gerektirdiğinden belirgin biçimde daha uzun olur: <ad>Ayşe</ad> ile "ad": "Ayşe" arasındaki fark, binlerce kayıtta ciddi bir boyut farkına dönüşür. YAML ise insan eliyle yazılan ayar dosyaları için rahattır, ama girintiye duyarlılığı ve tırnaksız değerleri kendiliğinden tipe çevirmesi hataya açıktır; bazı YAML sürümlerinde ülke kodu olarak yazılan tırnaksız NO değerinin mantıksal "hayır" olarak okunması bunun bilinen örneğidir. Makineler arası veri alışverişinde JSON'ın katılığı bir kusur değil, avantajdır.

API'lerde JSON nasıl kullanılır?

Modern web API'lerinin büyük çoğunluğu istek ve yanıt gövdesinde JSON taşır. Gövdenin JSON olduğu, HTTP başlığında Content-Type: application/json ifadesiyle bildirilir. Tipik bir akış şöyledir:

  1. İstemci, göndereceği veriyi kendi dilindeki nesneden JSON metnine çevirir; bu işleme serileştirme denir.
  2. İsteği doğru Content-Type başlığıyla gönderir.
  3. Sunucu gövdeyi ayrıştırır, alanları doğrular ve işlemi yapar.
  4. Yanıtı yine JSON olarak, uygun HTTP durum koduyla döndürür.
  5. İstemci yanıtı ayrıştırıp kendi nesnesine çevirir ve önce durum koduna, sonra gövdeye bakar.

Başarılı bir yanıt { "id": 1042, "durum": "onaylandi", "olusturma": "2025-03-14T09:30:00Z" } gibi görünebilir; hatalı bir istekte ise { "hata": { "kod": "gecersiz_alan", "mesaj": "yas alanı sayı olmalıdır" } } benzeri tutarlı bir hata gövdesi beklenir. İyi tasarlanmış bir API'de alan adları tek bir yazım kuralını izler (hep camelCase ya da hep snake_case), boş listeler null yerine [] olarak döner ve aynı alan bir yanıtta sayı, diğerinde metin olarak gelmez.

Sayılar, büyük kimlikler ve güvenlik

Standart, sayıların büyüklüğüne sınır koymaz; sınırı koyan, ayrıştıran dildir. JavaScript bütün sayıları 64 bit kayan noktalı olarak tuttuğu için 9007199254740991'den (2 üzeri 53 eksi 1) büyük tam sayıları kesin olarak temsil edemez. Sunucunun gönderdiği 19 haneli bir kayıt numarası tarayıcıda son haneleri değişmiş olarak belirebilir. Çözüm, büyük kimlikleri metin olarak taşımaktır: "id": "9223372036854775807".

Güvenlik tarafında iki temel kural vardır. Birincisi, JSON metni asla kod olarak çalıştırılmamalıdır; JavaScript'te eval yerine JSON.parse, diğer dillerde standart kütüphanenin ayrıştırıcısı kullanılmalıdır. İkincisi, ayrıştırılan veri güvenilir sayılmamalıdır: dışarıdan gelen her alanın tipi, uzunluğu ve değer aralığı doğrulanmalıdır.

Sık yapılan hatalar

  • Sondaki virgül: { "a": 1, "b": 2, } geçersizdir. JavaScript kodunda serbest olan bu yazım, JSON'da ayrıştırma hatasıdır.
  • Tek tırnak: { 'ad': 'Ali' } geçerli bir JavaScript nesnesidir ama geçerli JSON değildir.
  • Yorum satırı eklemek: JSON'da yorum yoktur. Açıklama gerekiyorsa "_aciklama" gibi bir alan kullanılabilir ya da yorum destekleyen JSON5, JSONC veya YAML gibi bir biçime geçilir; ancak bunlar standart ayrıştırıcılarla okunamaz.
  • Dile özgü değerler: undefined, NaN, Infinity, Python'daki None, True ve False JSON'da yoktur. Doğrusu null, true ve false biçimindedir ve küçük harfle yazılır.
  • Baştaki sıfırlar: 007 geçerli bir sayı değildir. Posta kodu, telefon numarası, plaka kodu gibi baştaki sıfırın anlamlı olduğu değerler zaten sayı değil metin olarak tutulmalıdır: "01" gibi.
  • Yinelenen anahtar: Aynı nesnede aynı anahtarı iki kez kullanmak çoğu ayrıştırıcıda hata vermez, sessizce sonuncuyu geçerli sayar; farklı kütüphaneler farklı davranabileceği için tehlikelidir.
  • Çifte kodlama: Zaten JSON olan bir metni yeniden serileştirmek, tırnakları kaçışlanmış tek bir string üretir. Yanıtta "{\"ad\":\"Ali\"}" gibi bir şey görüyorsanız sorun budur.
  • Görünmez karakterler: Dosyanın başındaki BOM işareti ya da kelime işlemciden kopyalanmış kıvrık tırnaklar ayrıştırıcıyı şaşırtır; hata mesajı "1. satır, 1. sütun" diyorsa ilk şüpheli budur.

Hata ayıklamanın en hızlı yolu, metni bir doğrulayıcıdan geçirmektir: Sorgulaa'daki JSON formatlayıcı gibi araçlar hem hatanın satır ve konumunu gösterir hem de sıkıştırılmış tek satırlık bir yanıtı girintili, okunur hale getirir. Yalnız, gerçek müşteri verisi ya da gizli anahtar içeren gövdeleri herhangi bir çevrimiçi araca yapıştırmadan önce hassas alanları temizlemek iyi bir alışkanlıktır.

Özetle

JSON, iki yapı (nesne ve dizi) ile dört basit değer türünden (metin, sayı, mantıksal, null) oluşan, dilden bağımsız bir veri alışveriş biçimidir. Gücü sadeliğinden gelir: öğrenmesi dakikalar sürer, her dilde hazır ayrıştırıcısı vardır ve insan tarafından okunabilir. Bedeli ise katılıktır: çift tırnak, virgül ve küçük harfli anahtar sözcükler konusunda hiçbir esneklik tanımaz; yorum, tarih ve ikili veri desteği yoktur. Belge ağırlıklı ve şema zorunluluğu yüksek işlerde XML, elle yazılan ayar dosyalarında YAML daha uygun olabilir; makineler arası veri taşımada ise JSON fiilî standarttır. Tarihleri ISO 8601 ile, büyük kimlikleri ve baştaki sıfırı anlamlı değerleri metin olarak taşımak, dışarıdan gelen her veriyi doğrulamak ve şüpheye düşünce bir doğrulayıcıya başvurmak, karşılaşılan sorunların büyük bölümünü daha ortaya çıkmadan önler.