Neden yeni bir paket?
Go’nun standart kütüphanesindeki encoding/json paketi yıllardır her yerde kullanılıyor. Ama bazı davranışları sürpriz yaratıyordu ve Go 1 uyumluluk sözü yüzünden bunları düzeltmek mümkün değildi. Düzeltmek, çalışan programları bozmak demekti. Go ekibi bu yüzden aynı işi yapan ama ayrı bir paket yazdı: encoding/json/v2. Go 1.25’te deneysel olarak gelmişti; Go 1.27 ile kararlı ve herkese açık. Ekip 4 Kasım’da yayımladığı blog yazısında neyin neden değiştiğini anlattı.
Eski paketin dertleri
- Yinelenen anahtarlar:
{"rol": "kullanici", "rol": "admin"}gibi bir nesneyi hata vermeden kabul ediyordu. Farklı sistemler bu durumda farklı değeri seçebildiği için açıklar çıktı. Apache CouchDB’deki CVE-2017-12635 tam olarak buydu. - Büyük/küçük harf: JSON’daki
"Admin"alanı, struct’takiadminetiketli alana da eşleniyordu. Bu hem şaşırtıcı hem de güvenlik açısından riskli. - Geçersiz UTF-8: JSON standardı (RFC 8259) geçerli UTF-8 istiyor, eski paket yine de kabul ediyordu.
- nil dilimler: Boş (nil) bir dilim ya da map
nullolarak yazılıyordu. Bazı istemciler bunu reddediyor; çoğu geliştirici[]ya da{}bekliyor. - Hız: Özel
UnmarshalJSONmetodları aynı veriyi iki kez ayrıştırmaya zorluyordu. İç içe yapılarda bu, maliyetin karesel büyümesine yol açabiliyordu.
v2’de ne değişti?
Yeni tasarım iki katmandan oluşuyor. encoding/json/jsontext sadece söz dizimiyle ilgileniyor: JSON’u akış olarak, token token okuyup yazıyor. encoding/json/v2 bunun üzerine Go değerlerine dönüştürme işini yapıyor. Özel kodlama yazmak için yeni MarshalJSONTo ve UnmarshalJSONFrom metodları doğrudan bu akışla çalışıyor, böylece aynı veriyi iki kez ayrıştırmak gerekmiyor.
Varsayılan davranışlar artık daha katı: Yinelenen anahtar ve geçersiz UTF-8 hata veriyor, alan eşleme harfe duyarlı, nil dilim [] olarak yazılıyor. omitempty, boş görünecek her değeri (null, "", [], {}) atlıyor. time.Duration için tek bir “doğru” gösterim olmadığından, onu nasıl yazacağını seçenekle belirtmen gerekiyor.
Performans tarafında Go ekibi Marshal’ın eskisiyle aşağı yukarı aynı hızda olduğunu, Unmarshal’ın ise bazı testlerde 10 kata kadar hızlı olduğunu söylüyor.
Geçiş nasıl olacak?
İyi haber: Eski encoding/json artık v2’nin üzerinde, eski davranışları açan seçeneklerle çalışıyor. İki sürüm birbirinin özel metodlarını tanıyor, yani bir projede ikisini yan yana kullanabilir, dosya dosya geçebilirsin. Taşınmak zorunlu da değil; eski API desteklenmeye devam ediyor.
Belirli bir eski davranışa ihtiyacın varsa onu seçenekle geri açabilirsin. Mesela v2 varsayılanlarını koruyup sadece yinelenen anahtarlara izin vermek için jsontext.AllowDuplicateNames(true) kullanılıyor. Sürüm notlarına göre Go 1.27’de bir sorun çıkarsa derleme sırasında GOEXPERIMENT=nojsonv2 ile eski uygulamaya dönmek de mümkün, ama bu seçeneğin ileride kaldırılması bekleniyor.
Düşün
- Projende bir JSON alanının farklı harflerle gelmesine sessizce güvenen bir yer var mı? v2’ye geçince ne olurdu?
- Daha katı bir ayrıştırıcı neden güvenlik açısından daha iyi? Yinelenen anahtar örneğinde iki sistemin farklı karar vermesi nasıl bir açığa dönüşür?
Videoyu izle
Kaynaklar (5, İngilizce)
- Better Stack: Go Fixed JSON (jsonv2) (video) (yeni sekmede açılır)
- The Go Blog: A new Go API for JSON (4 Kasım 2026) (yeni sekmede açılır)
- Go 1.27 Release Notes (yeni sekmede açılır)
- pkg.go.dev: encoding/json/v2 (yeni sekmede açılır)
- CVE-2017-12635 (Apache CouchDB, yinelenen JSON anahtarları) (yeni sekmede açılır)
Kendi cümlelerimizle yazılmış bir özettir, çeviri değildir. Tüm kaynaklar yukarıda.