Members gelistiriciGunlukleri Posted April 26, 2022 Members #1 Share Posted April 26, 2022 Her geçen gün tüm altyapısını Go’ya geçiren yeni bir firma duyuyoruz. Bunun sebebi de tahmin edersiniz ki Go’nun sunmuş olduğu kolaylıklar. İşte bunlardan birisi de JSON Data Streaming. Bu özellik hangi problemi çözüyor derseniz başlıkta da belirttiğim gibi büyük boyutlu JSON dosyalarınızı dertsiz tasasız okumaya yarıyor. Problem Tanımı Go ile normal bir şekilde JSON dosyası okumak gerçekten kolaydır. Elinizde bir JSON verisi bulunur. Buna karşılık gelen struct’ı (model) oluşturursunuz. Ardından Go’nun kendi json kütüphanesini json.Unmarshal() diyerek çalıştırırsınız. Böylece tüm json verisi memory’ye alınır ve uygulamanızda kullanılmaya hazırdır. Peki uygulama içerisinde memory’de kullanıma hazır hale gelen JSON verisinin 4KB değil de 4GB olduğunu düşünelim! Bilgisayarın RAM miktarına falan girip konuyu uzatmaya gerek yok, böyle bir durumda uygulamanız eninde sonunda tabiri caizse patlayacaktır. Çünkü standart json.Unmarshal() fonksiyonu JSON verisini bir bütün halinde okur ancak büyük boyutlu dosyaları doğru şekilde okumanın yolu, JSON Data Streaming ile onu obje obje okumaktır. Örnek JSON Konuyu anlatabilmek için bize güzel bir JSON verisi lazım. Bunun için Star Wars filmindeki oyunculardan oluşan bir API’den faydalanalım. The Star Wars API (https://swapi.co/) sitesinin sunduğu şu uca (https://swapi.co/api/people/) tıklayarak JSON verimizi görebilirsiniz. Tabi buradaki JSON verisi olduğu gibi kullanmadım çünkü sayfalama için Count, Next, Previous gibi şuan için ihtiyacımız olmayan özellikler vardı. Onun yerine çıktıyı, 87 isimin tamamından oluşan, dizi (array) şeklinde tek bir JSON haline getirdim. Bir kişi için genel yapı aşağıdaki gibidir. Tamamına yazının sonunda bağlantısı bulunan, bu yazı için hazırladığım örnek proje dosyalarından ulaşabilirsiniz. [ { "name": "Luke Skywalker", "height": "172", "mass": "77", "hair_color": "blond", "skin_color": "fair", "eye_color": "blue", "birth_year": "19BBY", "gender": "male", "homeworld": "https://swapi.co/api/planets/1/", "films": [ "https://swapi.co/api/films/2/", "https://swapi.co/api/films/6/", "https://swapi.co/api/films/3/", "https://swapi.co/api/films/1/", "https://swapi.co/api/films/7/" ], "species": [ "https://swapi.co/api/species/1/" ], "vehicles": [ "https://swapi.co/api/vehicles/14/", "https://swapi.co/api/vehicles/30/" ], "starships": [ "https://swapi.co/api/starships/12/", "https://swapi.co/api/starships/22/" ], "created": "2014-12-09T13:50:51.644000Z", "edited": "2014-12-20T21:17:56.891000Z", "url": "https://swapi.co/api/people/1/" }, ... } JSON’a Uygun Go Struct Yukarıdaki yapıya uygun Go Struct’ını elle yazabiliriz ancak onun yerine JSON to Go sitesinden direk karşılığını görebiliriz. Buna göre struct’ımız şu şekildedir. type People struct { Name string `json:"name"` Height string `json:"height"` Mass string `json:"mass"` HairColor string `json:"hair_color"` SkinColor string `json:"skin_color"` EyeColor string `json:"eye_color"` BirthYear string `json:"birth_year"` Gender string `json:"gender"` Homeworld string `json:"homeworld"` Films []string `json:"films"` Species []string `json:"species"` Vehicles []string `json:"vehicles"` Starships []string `json:"starships"` Created time.Time `json:"created"` Edited time.Time `json:"edited"` URL string `json:"url"` } Normal Method ile JSON Okuma JSON ve Struct’ımızı oluşturduktan sonra artık gerekli Go kodumuzu yazabiliriz. Aşağıdaki kod ile people.json dosyasındaki JSON verisini okuyup, kişilerin istediğimiz özelliğini ekrana yazdırabiliriz. package main import ( "encoding/json" "fmt" "io/ioutil" "os" "time" ) var err error type People struct { Name string `json:"name"` Height string `json:"height"` Mass string `json:"mass"` HairColor string `json:"hair_color"` SkinColor string `json:"skin_color"` EyeColor string `json:"eye_color"` BirthYear string `json:"birth_year"` Gender string `json:"gender"` Homeworld string `json:"homeworld"` Films []string `json:"films"` Species []string `json:"species"` Vehicles []string `json:"vehicles"` Starships []string `json:"starships"` Created time.Time `json:"created"` Edited time.Time `json:"edited"` URL string `json:"url"` } func main() { // JSON dosyasını açalım. jsonDosya, err := os.Open("people.json") if err != nil { fmt.Println(err) } defer jsonDosya.Close() // Dosya içeriğini okuyalım. icerik, err := ioutil.ReadAll(jsonDosya) if err != nil { fmt.Println(err) } // Dosyadaki veriyi ayrıştırıp değişkenimize aktaralım. var people []People json.Unmarshal(icerik, &people) // JSON verisindeki isimleri ekrana yazdıralım. for _, person := range people { fmt.Println(person.Name) } } JSON Data Streaming Methodu ile Okuma Büyük boyutlu dosyaları okumada temel olarak 2 fark bulunmaktadır. 1. json.Unmarshall() yerine, json.NewDecoder() kullanılır. 2. JSON’ı okuyup atayacağımız değişken dizi (array) değil, obje obje okuyacağımız için tekil struct olur. Aynı JSON verisini obje obje okuyarak, her obje üzerinde işlem yapmak için aşağıdaki Go kodunu kullanabiliriz. package main import ( "encoding/json" "fmt" "io/ioutil" "log" "os" "time" ) var err error type People struct { Name string `json:"name"` Height string `json:"height"` Mass string `json:"mass"` HairColor string `json:"hair_color"` SkinColor string `json:"skin_color"` EyeColor string `json:"eye_color"` BirthYear string `json:"birth_year"` Gender string `json:"gender"` Homeworld string `json:"homeworld"` Films []string `json:"films"` Species []string `json:"species"` Vehicles []string `json:"vehicles"` Starships []string `json:"starships"` Created time.Time `json:"created"` Edited time.Time `json:"edited"` URL string `json:"url"` } func main() { // JSON dosyasını açalım. jsonDosya, err := os.Open("people.json") if err != nil { fmt.Println(err) } defer jsonDosya.Close() dec := json.NewDecoder(jsonDosya) // Başlangıç verisini ([) okuyalım _, err = dec.Token() if err != nil { log.Println(err) } var person People // Bu döngü okunacak bir sonraki obje var ise devam eder. for dec.More() { err = dec.Decode(&person) if err != nil { log.Println(err) } fmt.Println(person.Name) } // Kapanış verisini (]) okuyalım _, err = dec.Token() if err != nil { log.Println(err) } } Quote . Link to comment Share on other sites More sharing options...