Go'da JSON Unmarshal Type Mismatch Hataları Nasıl Çözülür?
Go'da JSON işlerken unmarshal sırasında veri tipi uyuşmazlığı yaşamak çok yaygın. API'den gelen sayı bir string olarak gelebilir, boolean değer "true" yazısı şeklinde gelebilir ya da beklenmedik bir alan yapıya dahil edilebilir. Bu durumda unmarshal sessiz geçer ama veriler yanlış yerde kalır.
Sorunun kaynağını anlamak için önce basit bir örneğe bakalım. Diyelim ki bir API'den bu JSON'u alıyorsun:
1{"id": "123", "age": "25", "active": "true"}Ama struct'ında sayı ve boolean bekliyorsun:
1package main23import (4"encoding/json"5"fmt"6"log"7)89type User struct {10ID int `json:"id"`11Age int `json:"age"`12Active bool `json:"active"`13}1415func main() {16jsonData:= `{"id": "123", "age": "25", "active": "true"}`17var user User18err:= json.Unmarshal([]byte(jsonData), &user)19if err!= nil {20log.Println("Hata:", err)21}22fmt.Printf("%+v\n", user) // ID ve Age 0 olacak23}Bu kod çalışacak ama `ID` ve `Age` sıfır olarak kalacak çünkü string'i int'e otomatik dönüştürmez.
Çözüm için custom `UnmarshalJSON` metodu yazabilirsin:
1type User struct {2ID int `json:"id"`3Age int `json:"age"`4Active bool `json:"active"`5}67func (u *User) UnmarshalJSON(data []byte) error {8type Alias User9aux:= &struct {10ID string `json:"id"`11Age string `json:"age"`12Active string `json:"active"`13}{14Alias: (*Alias)(u),15}1617if err:= json.Unmarshal(data, &aux); err!= nil {18return err19}2021var errMsg string22if id, err:= strconv.Atoi(aux.ID); err == nil {23u.ID = id24} else {25errMsg += "ID dönüştürülemedi; "26}2728if age, err:= strconv.Atoi(aux.Age); err == nil {29u.Age = age30} else {31errMsg += "Age dönüştürülemedi; "32}3334u.Active = aux.Active == "true" || aux.Active == "1"3536if errMsg!= "" {37return fmt.Errorf(errMsg)38}39return nil40}Beklenen çıktı:
1{ID:123 Age:25 Active:true}Daha basit bir yol: API'den gelen veriyi önce `map[string]interface{}` olarak parse edip sonra type assertion kullanabilirsin. Veya struct tag'inde `string` option'ını kullanabilirsin (sayı alanlar için):
1type User struct {2ID int `json:"id,string"`3Age int `json:"age,string"`4Active bool `json:"active"`5}Bu tag Go'ya "bu alan JSON'da string olabilir ama int'e dönüştür" der. Sadece sayı tipleri için çalışır.
Sık hatalar: Struct field'larının public olması (büyük harfle başlaması) gerekir, aksi halde unmarshal onları görmez. JSON tag'indeki alan adını API'nin döndüğü adla eşleştir. Type mismatch'i erken yakala; production'da sessiz başarısızlık veriye zarar verebilir.
0 yorum