---
id: 61f2009278a5f7366f79395da59447cf
author: lemonmint
title: Go 1.25 encoding/json/v2 davranış değişiklikleri ve v1 uyumluluk katmanının analizi
description: Go 1.25 deneysel özelliği (goexperiment.jsonv2) ile tanıtılan encoding/json/v2'nin büyük/küçük harf duyarlı eşleştirmesi, omitempty/omitzero anlamsal değişiklikleri, nil dilim/harita serileştirmesi ve seçenekleri karşılaştırılmaktadır.
language: tr
date: 2025-06-20T05:38:20.100520237Z
path: /blog/posts/go-1-25-encoding-json-v1-vs-v2-z74a36b08
category: release
---

Go'nun `encoding/json` paketi v2, mevcut v1'in çeşitli dezavantajlarını (tutarsızlık, şaşırtıcı davranışlar, performans sorunları) gidermek için geliştirilmiş yeni bir uygulamadır. Bu özellik, `goexperiment.jsonv2` derleme etiketi (build tag) aracılığıyla etkinleştirilen deneysel bir özelliktir.

En önemli nokta, **v2 etkinleştirildiğinde v1'in, v2 uygulaması üzerinde v1'in davranışını taklit eden bir uyumluluk katmanı olarak çalışmasıdır**. Bu, `v2_v1.go` dosyasındaki `DefaultOptionsV1()` fonksiyonu aracılığıyla gerçekleştirilir. Yani v2, v1'in davranışını tam olarak yeniden üretebilen seçenekler sunarken, aynı zamanda daha katı ve öngörülebilir yeni varsayılan davranışlar da önerir.

v2'nin başlıca hedefleri şunlardır:

1. **Doğruluk ve öngörülebilirliğin artırılması**: Varsayılan olarak daha katı kurallar (ör. büyük/küçük harf duyarlılığı, yinelenen anahtarların yasaklanması) uygulayarak beklenmeyen davranışları azaltır.
2. **Performansın iyileştirilmesi**: Ayrıştırma (parsing) ve kodlama (encoding) motorları, verimliliği artırmak için yeniden tasarlanmıştır.
3. **Esneklik ve denetimin genişletilmesi**: Geliştiricilerin JSON işleme yöntemlerini ayrıntılı biçimde kontrol edebilmesi için kapsamlı bir seçenek sistemi sunulmuştur.

---

## Başlıca Anlam/Davranış Farklılıkları

V1 ile v2 arasındaki davranış farklılıkları, `v2_test.go` dosyası temel alınarak madde madde özetlenmiştir.

### 1. Alan Adı Eşleştirme (Büyük/Küçük Harf Duyarlılığı)

- **v1 davranışı**: JSON nesne üyelerini Go yapı alanlarına unmarshal ederken **büyük/küçük harfe duyarsız (case-insensitive)** eşleştirme yapar. Hem `"FirstName"` hem de `"firstname"`, `FirstName` alanına eşlenir.
- **v2 davranışı**: Varsayılan olarak **büyük/küçük harfe duyarlı (case-sensitive)** çalışır ve yalnızca tam olarak eşleşen alanları eşler.
- **Değişikliğin nedeni**: Büyük/küçük harfe duyarsız eşleştirme, beklenmeyen davranışların kaynağı olabilir ve eşleşmeyen alanların işlenmesinde performans düşüşüne yol açar. v2, daha açık ve öngörülebilir davranışı varsayılan olarak benimsemiştir.
- **İlgili seçenekler**: v2'de, `json:"...,case:ignore"` etiket seçeneği ile alan bazında büyük/küçük harf duyarsızlığı açıkça etkinleştirilebilir veya `json.MatchCaseInsensitiveNames(true)` seçeneği genel olarak uygulanabilir.

### 2. `omitempty` Etiket Seçeneğinin Anlamındaki Değişiklik

- **v1 davranışı**: Alanları Go değerinin "boş (empty) durumuna" göre atlar. Burada "boş durum", `false`, `0`, `nil` işaretçi/arayüz ve uzunluğu 0 olan dizi/dilim/harita/dizgi anlamına gelir.
- **v2 davranışı**: Alanları kodlanmış JSON değerinin "boş durumuna" göre atlar. Yani `null`, `""`, `{}` veya `[]` olarak kodlanan değerler atlanır.
- **Değişikliğin nedeni**: v1'deki tanım Go'nun tür sistemine bağımlıdır. v2 ise JSON tür sistemini temel alarak daha tutarlı bir davranış sunar. Örneğin v1'de `bool` türündeki `false` değeri atlanırken, v2'de `false` boş olmayan bir JSON değeri olduğu için atlanmaz. v2, v1'deki `omitempty`'nin `0` veya `false` değerlerine uygulanan davranışının yerini alabilmesi için `omitzero` seçeneğini ekler.
- **İlgili seçenekler**: v2'de v1 ile aynı davranışın istenmesi durumunda `json.OmitEmptyWithLegacyDefinition(true)` seçeneği kullanılır.

### 3. `string` Etiket Seçeneğinin Davranış Değişikliği

- **v1 davranışı**: Sayı, mantıksal ve dizgi türündeki alanlara uygulanır. İlgili değeri bir JSON dizgisi içinde yeniden kodlar (ör. `int(42)` -> `"42"`). Bileşik türlerin (dilim, harita vb.) içindeki değerlere özyinelemeli olarak uygulanmaz.
- **v2 davranışı**: **Yalnızca sayısal türlere uygulanır** ve özyinelemeli olarak işler. Yani `[]int` gibi bir dilimin içindeki sayılar da JSON dizgisi olarak kodlanır.
- **Değişikliğin nedeni**: `string` seçeneğinin temel amacı, 64 bitlik tam sayıların hassasiyet kaybını önlemek için sayıları dizgi olarak temsil etmektir. v1'in davranışı sınırlı ve tutarsızdı. v2, bu temel kullanıma odaklanmış ve davranışı özyinelemeli olarak genişleterek daha kullanışlı hale getirmiştir.
- **İlgili seçenekler**: v1'in davranışını taklit etmek için `json.StringifyWithLegacySemantics(true)` seçeneği kullanılabilir.

### 4. `nil` Dilim ve Harita Marshal İşlemi

- **v1 davranışı**: `nil` dilimler ve `nil` haritalar `null` olarak marshal edilir.
- **v2 davranışı**: Varsayılan olarak `nil` dilimler `[]` (boş dizi), `nil` haritalar ise `{}` (boş nesne) olarak marshal edilir.
- **Değişikliğin nedeni**: `nil`, Go dilinin uygulama ayrıntısıdır ve dilden bağımsız bir JSON biçimine bunu yansıtmak uygun değildir. Boş koleksiyonları temsil eden `[]` ve `{}` daha yaygın bir gösterimdir.
- **İlgili seçenekler**: v2'de `json.FormatNilSliceAsNull(true)` veya `json.FormatNilMapAsNull(true)` seçenekleriyle v1'deki gibi `null` olarak marshal edilebilir.

### 5. Dizi Unmarshal İşlemi

- **v1 davranışı**: Go dizisine (`[N]T`) unmarshal ederken JSON dizisinin uzunluğu Go dizisinin uzunluğuyla farklı olsa da hata oluşturmaz. Uzunluk kısaysa kalan alanlar sıfır değerle doldurulur, uzunsa fazla kısım atılır.
- **v2 davranışı**: JSON dizisinin uzunluğu Go dizisinin uzunluğuyla **tam olarak eşleşmelidir**. Aksi takdirde hata oluşur.
- **Değişikliğin nedeni**: Go'da sabit boyutlu dizilerin uzunluğu çoğu zaman önemli bir anlam taşır. v1'in davranışı, verinin sessizce kaybolmasına yol açabilir. v2, daha katı kurallarla doğruluğu artırmıştır.
- **İlgili seçenekler**: v1'in davranışını taklit etmek için `json.UnmarshalArrayFromAnyLength(true)` seçeneği kullanılabilir.

### 6. `time.Duration` İşleme

- **v1 davranışı**: `time.Duration`, dahili olarak `int64` gibi ele alınır ve nanosaniye cinsinden bir JSON sayısı olarak kodlanır.
- **v2 davranışı**: `time.Duration.String()` metodu kullanılarak `"1h2m3s"` gibi biçimde bir JSON dizgisi olarak kodlanır.
- **Değişikliğin nedeni**: Nanosaniye cinsinden sayılar okunabilirliği azaltır; `time.Duration`'ın standart dizgi gösterimi daha kullanışlıdır.
- **İlgili seçenekler**: v1'in davranışını kullanmak için `json:",format:nano"` etiket seçeneği veya `json.FormatTimeWithLegacySemantics(true)` seçeneği kullanılabilir.

### 7. Geçersiz UTF-8 İşleme

- **v1 davranışı**: Marshal/unmarshal sırasında bir dizgi içinde geçersiz UTF-8 baytları varsa bunları Unicode yedek karakteri (`\uFFFD`) ile **sessizce değiştirir**.
- **v2 davranışı**: Varsayılan olarak geçersiz UTF-8 ile karşılaşıldığında **hata döndürür**.
- **Değişikliğin nedeni**: Verinin sessizce bozulmasını önlemek ve daha katı JSON standardını (RFC 7493) izlemek amaçlanmıştır.
- **İlgili seçenekler**: v1'in davranışını taklit etmek için `jsontext.AllowInvalidUTF8(true)` seçeneği kullanılabilir.

### 8. Yinelenen Nesne Üye Adlarının İşlenmesi

- **v1 davranışı**: Bir JSON nesnesinde aynı adlı üyelerin yinelenmesine izin verir. Son görülen değer önceki değerin üzerine yazılır.
- **v2 davranışı**: Varsayılan olarak yinelenen üye adı bulunduğunda **hata döndürür**.
- **Değişikliğin nedeni**: RFC 8259 standardı yinelenen adların davranışını tanımlamadığından, uygulamalar farklı davranabilir. Bu durum bir güvenlik açığının kaynağı olabilir. v2, bunu açıkça reddederek doğruluğu ve güvenliği artırmıştır.
- **İlgili seçenekler**: v1'in davranışını taklit etmek için `jsontext.AllowDuplicateNames(true)` seçeneği kullanılabilir.

---

## Uygulama ve Mimari Farklılıklar

- **v1**: `decode.go` içindeki `decodeState` ve `scanner.go` içindeki elle yazılmış durum makinesine (state machine) büyük ölçüde bağımlıdır. Bu, ayrıştırma mantığı ile anlamsal analizin sıkı biçimde birleşik olduğu tekparça (monolitik) bir yapıdır.
- **v2**: Mimari daha modüler hale getirilmiştir.
  - **`encoding/json/jsontext`**: Düşük seviyeli, yüksek performanslı bir JSON belirteçleyicisi (tokenizer) (`Decoder`) ve kodlayıcısı (`Encoder`) sunar. Bu paket yalnızca JSON'un sözdizimsel (syntax) yönlerine odaklanır.
  - **`encoding/json/v2`**: `jsontext` üzerine inşa edilmiştir ve Go türleri ile JSON değerleri arasındaki anlamsal (semantic) dönüşümleri yönetir.
  - Bu ayrım sayesinde sözdizimsel ayrıştırma ile anlamsal analiz birbirinden ayrılmış, kodun açıklığı ve performansı artmıştır.

---

## v2'nin Yeni API ve Özellikleri

v2, `json.Options` sistemi aracılığıyla çok esnek bir denetim imkânı sunar.

- **`json.Options`**: Marshal/unmarshal davranışını değiştiren seçeneklerin kümesidir.
- **`json.JoinOptions(...)`**: Birden fazla seçeneği tek bir seçenekte birleştirir.
- **`WithMarshalers` / `WithUnmarshalers`**: `Marshaler`/`Unmarshaler` arayüzlerini uygulamadan belirli bir tür için serileştirme/seri durumdan çıkarma mantığı eklemeye olanak tanıyan güçlü bir özelliktir. Bu, özellikle harici paketlerdeki türlerle çalışırken yararlıdır.
- **Yeni seçenekler**: `RejectUnknownMembers`, `Deterministic(false)`, `FormatNilSliceAsNull` gibi v1'de mümkün olmayan çeşitli davranış denetimleri artık kullanılabilir.

---

## Sonuç

`encoding/json` v2, v1'deki deneyimlerden yola çıkarak **doğruluk, performans ve esnekliği** önemli ölçüde geliştiren çağdaş bir uygulamadır. Varsayılan davranışlar daha katı hale gelmiş olsa da, gelişmiş `Options` sistemi sayesinde v1'in tüm davranışları tam olarak desteklenir; böylece mevcut kodla uyumluluk korunarak v2'nin avantajları kademeli olarak benimsenebilir.

- **Yeni projeler** için v2'nin varsayılan olarak kullanılması önerilir.
- **Mevcut projeler**, `jsonv1`'i olduğu gibi kullanmaya devam edebilir veya `jsonv2`'ye geçiş yaparken `DefaultOptionsV1()` aracılığıyla v2'nin katı davranışlarını kademeli olarak benimseyen bir strateji izleyebilir.
